Developing a QA tool
Adding Tool and Configurators
One of the QA Tools' objectives is to make it easy to configure tools.
To create a new tool:
- Create a new directory in the
src/Tooldirectory and give it a descriptive name, preferably the actual name of the tool. - Create a class with the same name that extends
\Ibuildings\QaTools\Core\Tool\AbstractToolin this new directory. - Add instance of you new class should be added to the
\Ibuildings\QaTools\Core\Application\Application::getRegisteredTools()method in order for it to be configurable. - Specify for what projects the tool may be added in a new file
src/Tool/<ToolName>/Resources/config/configurators.yml. - Create a configurator in
\Ibuildings\QaTools\Tool\<ToolName>\Configurator\<ConfiguratorName>. - Create templates for configuration files in
src/Tool/<ToolName>/Resources/templates.
Fix the tests you broke as a result of creating the new tool:
- Add Composer package stub in
tests/composer/packages/<package>/composer.jsonand add it to the list of repositories inIbuildings\QaTools\ComposerTest\Composer::mockRepositories(). - Make sure the question is answered for adding your tool in:
tests/system/specs/000_can-configure-a-php-project.tcltests/system/specs/010_developer-need-not-reanswer-previously-answered-questions.tcltests/system/specs/020_aborts-on-composer-dependency-conflict.tcl
- Test your configurator in
tests/unit/Tool/<ToolName>/Configurator/<ToolName>ConfiguratorTest.phptake a look at the other tests for examples.
Configurators are responsible for configuring a tool for a specific project type.
By default, the tool's configurators are configured in its src/Tool/<ToolName>/Resources/config/configurators.yml file.
To modify which configuration file is used or to add configuration files for this tool,
override the inherited getConfigurationFiles method.
Configurators should be added under the tool's namespace (i.e. \Ibuildings\QaTools\Tool\<ToolName>\Configurator\<ConfiguratorName>) and
are defined as a service through the tool's configurators.yml file.
A tag has to be added to the configurator's definition to indicate which project types it supports:
services:
qa_tools.tool.configurator.<configurator_name>:
class: Ibuildings\QaTools\Tool\<ToolName>\Configurator\<ConfiguratorName>
tags:
- name: qa_tools.tool
project_type: <project_type>
A finite list of supported project types are hard-coded in \Ibuildings\QaTools\Core\Project\ProjectType.
Which project types apply for a certain project are determined through the interview process using the ProjectConfigurator.
The configuration process can be defined in the Configurator's configure
method, in which it can use the Interviewer, TaskDirectory and
TaskHelperSet. Templating and such are available through the
TaskHelperSet.
These can be used to help register requirements with the
TaskDirectory. A tool's templates should reside under
src/Tool/<ToolName>/Resources/templates.
The Interviewer is used for IO interaction.
Interview API
The Interviewer is responsible for the interaction with the developer. It can provide the developer with information using the
tell and warn methods and acquire information from him using the ask method. While the tell and warn methods
accept strings as their arguments, the ask method is requires a specific Question.
TextualQuestion
A TextualQuestion is an open question that expects a TextualAnswer as a response.
Optionally, a TextualAnswer can be given as a default answer as a second argument.
$answer = $interviewer->ask(new TextualQuestion('What is your favorite food?', new TextualAnswer('Pizza'));
Alternatively, a TextualQuestion can be created as using a factory:
$answer = $interviewer->ask(Question::create('What is your favorite food?', 'Pizza'));
YesOrNoQuestion
A YesOrNoQuestion is a closed question that expects a YesOrNoAnswer as a response.
Optionally, a YesOrNoAnswer can be given as a default answer as a second argument.
Since there are only two possible answers, YesOrNoAnswers are created using named constructors.
$answer = $interviewer->ask(new YesOrNoQuestion('Do you like Mexican food?', YesOrNoAnswer::yes());
Alternatively, a YesOrNoQuestion can be created as using a factory:
$answer = $interviewer->ask(Question::createYesOrNo('Do you like Mexican food?', YesOrNoAnswer::YES));
MultipleChoiceQuestion
A MultipleChoiceQuestion is a closed question that expects a TextualAnswer selected from a list of Choices,
its second argument, as a response.
Optionally, a TextualAnswer can be given as a default answer as a third argument.
$answer = $interviewer->ask(new MultipleChoiceQuestion('What would you like to eat?',
new Choices([
new TextualAnswer('Caesar Salad'),
new TextualAnswer('Cheese Sandwich'),
new TextualAnswer('Chicken Wings')
]),
new TextualAnswer('Chicken Wings')
));
Alternatively, a MultipleChoiceQuestion can be created as using a factory:
$answer = $interviewer->ask(Question::createMultipleChoice('What would you like to eat?', [
'Caesar Salad',
'Cheese Sandwich',
'Chicken Wings'
],
'Chicken Wings'
));
ListChoiceQuestion
A ListChoiceQuestion is a closed question that expects Choices selected from a list of Choices,
its second argument, as a response.
Optionally, Choices can be given as a default answer as a third argument.
$answer = $interviewer->ask(new ListChoiceQuestion('Which of the following would you like to eat next?',
new Choices([
new TextualAnswer('Caesar Salad'),
new TextualAnswer('Cheese Sandwich'),
new TextualAnswer('Chicken Wings')
]),
new Choices([
new TextualAnswer('Caesar Salad'),
new TextualAnswer('Cheese Sandwich'),
])
));
Alternatively, a ListChoiceQuestion can be created as using a factory:
$answer = $interviewer->ask(Question::createMultipleChoice('Which of the following would you like to eat next?', [
'Caesar Salad',
'Cheese Sandwich',
'Chicken Wings'
],
'Caesar Salad',
'Chick Wings'
));