Skip to content

Hooks

In a workflow, you can use provider plugin functions. Generator plugins can also generate jobs that use provider plugin functions.

Sometimes you may want to customize the resulting steps. If you are calling those functions directly, you can add steps before or after the call, but this can be tedious if you have many calling points. And if you are using generator plugins, you have no control.

The OpenTestFactory orchestrator supports hooks that help in this regard. A hook is a point where you can alter the default behavior.

Hooks are currently defined for provider plugin functions: you can define steps that will be added before the function steps or after the function steps.

Hooks are statements of the form:

hooks:
- name: my pre-checkout hook
  events:
  - categoryPrefix: actions
    category: checkout
  before:
  - run: echo about to perform a checkout

They have mandatory name and events parts. They must also have either a before part or an after one (or both). They may have a conditional part, if, too, to restrict their scopes.

You can define hooks in your workflow. You can also define hooks in your provider configuration file (at installation/configuration time), that will only apply to functions provided by the plugin.

Defining hooks in your workflow

In your workflow you can add a hooks section. In this example, hello world will be echoed in the console just before running the Robot Framework test.

apiVersion: opentestfactory.org/v1alpha1
kind: Workflow
metadata:
  name: RobotFramework Example
hooks:
  - name: robot setup
    events:
    - category: robot
      categoryPrefix: robotframework
    before:
    - run: echo hello robot
jobs:
  keyword-driven:
    runs-on: [windows, robotframework]
    steps:
    - uses: actions/checkout@v2
      with:
        repository: https://github.com/robotframework/RobotDemo.git
    - run: 'dir'
      working-directory: RobotDemo
    - uses: robotframework/robot@v1
      with:
        datasource: RobotDemo/keyword_driven.robot

Defining hooks in your provider configuration file

Please refer to “Hooks for plugin providers” for examples and instructions if you want to define hooks in your provider configuration file.

Use cases

Additional attachments

Context

On your site, you are using a specific library with your testing framework that takes screenshots during test execution and put them in a known directory (target/screenshots).

The screenshots will have random names, but are all in PNG format, with the .png file name extension.

You want to have those screenshots attached to the test case execution in your test case manager.

Implementation

hooks:
- name: screenshots loader
  events:
  - categoryPrefix: robotframework
    category: execute
  after:
  - uses: actions/get-files
    with:
      pattern: *.png
    working-directory: target/screenshots

If you are unsure of the directory content before running the test, you can add a before section to ensure it is cleaned:

  before:
  - uses: actions/delete-file
    with:
      path: *.png
    working-directory: target/screenshots
    continue-on-error: true

The continue-on-error argument is added so that the job can continue if the directory does not yet exist.

You can insert this hook in your workflow or in your provider plugin configuration file.

JUnit detailed execution logs

Context

JUnit execution logs can be verbose, but they are helpful when trying to investigate technical issues.

The JUnit provider stores its execution log in a target/junit-run-log.txt file.

You want to have this execution log displayed if the test execution fails.

Implementation

hooks:
- name: execution logs on failure (linux)
  events:
  - category: execute
  - category: junit
  if: runner.os == 'linux'
  after:
  - run: find . -name junit-run-log.txt -print | xargs cat
    if: failure()
- name: execution logs on failure (windows)
  events:
  - category: execute
  - category: junit
  if: runner.os == 'windows'
  after:
  - run: '@for /f %%i in (''dir /b/s "junit-run-log.txt"'') do @type %%i'
    if: failure()

You insert this hook in your JUnit plugin configuration file. (You should do it in the plugin configuration file so that it applies to all workflows. You can test it in a workflow, though.)

Audit logs

Context

As a platform manager, you want to record whenever the execute and cucumber functions of the Cucumber plugin are called. You have Linux and Windows execution environments.

Implementation

hooks:
- name: audit log (linux)
  events:
  - category: execute
  - category: cucumber
  if: runner.os == 'linux'
  before:
  - run: logger -n 192.168.1.2 "Cucumber is about to be used"
- name: audit log (windows)
  events:
  - category: execute
  - category: cucumber
  if: runner.os == 'windows'
  before:
  - run: eventcreate /Id 7777 /D "Cucumber is about to be used" /T INFO /L system

You insert this hook in your Cucumber plugin configuration file. (You should do it in the plugin configuration file so that it applies to all workflows. You can test it in a workflow, though.)

Start and stop a service

Context

In order to save resources, you want to start a specific service before running your test using a given testing framework, and you want to stop if after the test execution.

You want this behavior for explicit use of the testing framework as well as for implicit use (for tests executed via a generator plugin).

Implementation

hooks:
- name: manage myservice
  events:
  - categoryPrefix: robotframework
    category: execute
  - categoryPrefix: robotframework
    category: robot
  before:
  - run: service start myservice
  after:
  - run: service stop myservice
    if: always()
    continue-on-error: true

The continue-on-error: argument is used so that the job can continue even if something went wrong while stopping the service.

The if: always() argument is used so that the service is stopped even if an execution error occurred in a previous step.

You insert this hook in your Robot Framework plugin configuration file. (You should do it in the plugin configuration file so that it applies to all workflows. You can test it in a workflow, though.)

Conditional behavior

Context

As a platform manager, you want to provide an optional database service to your users when using a given function.

They will have to set a NEED_DATABASE environment variable to activate it.

Example
jobs:
  my_job:
    ...
    steps:
    ...
    - uses myplugin/myfunction
      variables:
        NEED_DATABASE: yes
    ...

They may also choose to set the environment variable at job- or workflow-level, so that the service is available for all functions in the job or workflow, respectively.

Implementation

hooks:
- name: manage database
  events:
  - categoryPrefix: myplugin
    category: myfunction
  if: variables.NEED_DATABASE == 'yes'
  before:
  - run: start_db
  after:
  - run: stop_db
    if: always()
    continue-on-error: true

This differs from the ‘Start and stop a service’ use-case in that no code is added if the feature is not used.

You insert this hook in your myplugin plugin configuration file. (You should do it in the plugin configuration file so that it applies to all workflows. You can test it in a workflow, though.)

Next steps

Here are some helpful resources for taking your next steps with the OpenTestFactory hooks: