5.6 KiB
How does Quilla work?
Quilla is a wrapper on Selenium to allow for test writers to create their testing scenarios focusing not on how Selenium works, but on how their tests are executed. As such, the goal was to create a testing syntax that focuses on legibility, and uses minimal required setup. For further information on the specifics of how Quilla translates the JSON test files into workable code and runs the validations, read on.
Code execution flow
When Quilla is called, it will first create and initialize the plugin manager. This is done by first loading all the plugins that are exposed through python entrypoints, then attempting to discover a uiconf.py
file in the plugin root directory (which is at this time just the calling directory).
Next, Quilla will create the parser and pass it to the quilla_addopts
hook to allow plugins to register new parser options. If the user has specified that they are passing in a filename, the file will then be read and the contents of the file will be saved as a string. It will then parse the CLI options and use them to create the default context.
The context object is initialized as follows:
- A snapshot of the
PATH
variable is taken - The debug configurations are set
- The driver path is added to the system
PATH
environment variable - The definition files will be loaded and merged
Once the context is initialized, it will be passed to the quilla_configure
hook to allow plugins to alter the context.
When the configuration is finalized, the contents of the file will be loaded with the default JSON loader from python into a dictionary. This dictionary will then be processed as follows:
- If the quilla test file has a 'definitions' key, it will be loaded and merged with the existing definitions
- All specified browser names will be resolved into a
BrowserTargets
enum. - Each step will be processed as such:
- The action name for the step will be resolved into a
UITestActions
enum - If the action is a
Validate
action, the type will be resolved into aValidationTypes
enum- Based on the
ValidationTypes
, the appropriateValidationStates
subclass will be selected and the state will be resolved
- Based on the
- If there are parameters specified, they will be checked:
- If the "source" parameter is specified, it will be resolved into a
OutputSources
enum
- If the "source" parameter is specified, it will be resolved into a
- The action name for the step will be resolved into a
- The
UIValidation
object is then created with the fully-resolved dictionary- A
StepsAggregator
instance is created to manage the creation of all proper step objects- Each step in the list of step dictionaries will be resolved into the appropriate type, either a
TestStep
or something that can be resolved by theValidation
factory class
- Each step in the list of step dictionaries will be resolved into the appropriate type, either a
- For each browser specified in the JSON file, a copy of the
StepsAggregator
object will be created and passed into a newBrowserValidation
object
- A
After the UIValidation
object is created, it is passed to the quilla_prevalidate
plugin hook. This hook is able to mutate the object however it sees fit, allowing end-users to manipulate steps dynamically.
When the UIValidation
object is finalized, it will then call validate_all()
to execute all browser validations sequentially. The order in which the browsers will be validated is the same order in which they were specified. When calling the validate_all
function, the following will occur for each browser target:
- An appropriate driver will be created and configured according to the runtime context, opening up a blank page
- The driver will navigate to the root path of the validation
- The
BrowserValidation
object will bind the current driver to itself, to each of its steps (through theStepsAggregator
), and to the runtime context - Each step will be executed in order, performing the following:
- The action function is selected. For a
TestStep
, it is resolved based on the action associated to itsUITestActions
value through a dictionary selector. For aValidation
, this is determined based on theValidationStates
subclass value (i.e. theXPathValidationStates
, etc) - If the action produces a report, add it to the list of resulting reports
- If the action produces an exception, a
StepFailureReport
will be generated and the rest of the steps will not be executed. This is substantially different from theValidation
behaviour: theValidate
action only describes the state of the page, so it does not necessarily mean that the steps following it are not able to be performed. Since almost every other action actually causes the state of the page to change, allowing the test to continue would mean allowing the execution of the next steps in an inconsistent state.
- The action function is selected. For a
- Once all steps have been executed, or an uncaught exception happens on the
StepsAggregator
(which will happen if thesuppress_exceptions
flag is set toFalse
in the context object), theBrowserValidation
will close the browser window, unbind the driver from itself, the steps, and the context. - If no exception was raised, the list of report objects will be returned
After each browser finishes executing, the returned reports are all aggregated and put into a ReportSummary
, which is ultimately returned.
Once the final ReportSummary
has been generated, it is passed (along with the runtime context) to the quilla_postvalidate
hook.
Finally, the entire ReportSummary
is converted into JSON alongside any outputs created by the test actions, which are then printed to the standard output. If the ReportSummary
contains any failures, or critical failures, it will then return the exit code of 1, otherwise it will return an exit code of 0.