Internal modules

check - collection of different checks

class catcher.steps.check.All(body: dict, negative=False)[source]

Bases: catcher.steps.check.Operator

Fail if any check on the iterable fail.

Input:
Of:The source to check. Can be list or dictionary.
<check>:Check to perform on each element of the iterable.
Examples:

Pass if all elements of var has k == a

check:
    all:
        of: '{{ var }}'
        equals: {the: '{{ ITEM.k }}', is: 'a'}
operation(variables) → bool[source]
operator(data)[source]
class catcher.steps.check.And(body: dict, negative=False)[source]

Bases: catcher.steps.check.Operator

Fail if any of the conditions fails.

Input:The list of other checks.
Examples:

This is the same as 1 in list and list[1] != ‘b’ and list[2] > 2

check:
    and:
        - contains: {the: 1, in: '{{ list }}'}
        - equals: {the: '{{ list[1] }}', is_not: 'b'}
        - equals: {the: '{{ list[2] > 2 }}', is_not: true}
end
operation(variables) → bool[source]
class catcher.steps.check.Any(body: dict, negative=False)[source]

Bases: catcher.steps.check.All

Fail if all checks on the iterable fail.

Input:
Of:The source to check. Can be list or dictionary.
<check>:Check to perform on each element of the iterable.
Examples:

Fail if var doesn’t contain element with k == a

check:
    any:
        of: '{{ var }}'
        equals: {the: '{{ ITEM.k }}', is: 'a'}
operator(data)[source]
class catcher.steps.check.Contains(body: dict, negative=False)[source]

Bases: catcher.steps.check.Operator

Fail if list of dictionary doesn’t contain the value

Input:
The:value to contain
In:variable to check
Not_in:inverted in. Only one can be used at a time.
Examples:

Check ‘a’ not in variable ‘list’

check:
    contains: {the: 'a', not_in: '{{ list }}'}

Check variable ‘dict’ has key a.

check:
    contains: {the: 'a', in: '{{ dict }}'}
determine_source(body: dict)[source]
operation(variables: dict)[source]
static to_long_form(source: any, value: any)[source]
class catcher.steps.check.Equals(body: dict, negative=False)[source]

Bases: catcher.steps.check.Operator

Fail if elements are not equal

Input:
The:value
Is:variable to compare
Is_not:inverted is. Only one can be used at a time.
Examples:

Check ‘bar’ equals variable ‘foo’

check: {equals: {the: 'bar', is: '{{ foo }}'}}

Check list’s third element is not greater than 2.

check: {equals: {the: '{{ list[2] > 2 }}', is_not: true}}
determine_source(body: dict)[source]
operation(variables: dict) → bool[source]
static to_long_form(source: any, value: any)[source]
class catcher.steps.check.Or(body: dict, negative=False)[source]

Bases: catcher.steps.check.And

Fail if all conditions fail.

Input:The list of other checks.
Examples:

This is the same as 1 in list or list[1] != ‘b’ or list[2] > 2

check:
    or:
        - contains: {the: 1, in: '{{ list }}'}
        - equals: {the: '{{ list[1] }}', is_not: 'b'}
        - equals: {the: '{{ list[2] > 2 }}', is_not: true}
end

echo - write data to stdout or file

class catcher.steps.echo.Echo(_path: str = None, _body=None, to=None, from_file=None, **kwargs)[source]
Input:
From:data source. Can be variable or constant string
From_file:file in resources.
To:output to file. Optional If not set - stdout will be used.

Has short from which just prints variable to stdout.

Examples:

Use short form to print variable to stdout

echo: '{{ var }}'

Print constant + variable to file

echo: {from: 'constant and {{ var }}', to: debug.output}

Use echo to register new variable

echo: {from: '{{ RANDOM_STR }}@test.com', register: {user_email: '{{ OUTPUT }}'}}

Read file content to a variable

echo: {from_file: debug.output, to: '{{ user_email }}'}

loop - loop over the data

class catcher.steps.loop.Loop(_get_action=None, _get_actions=None, **kwargs)[source]
Input:
While:perform action while the condition is true
  • if: your condition. It can be in short format: if: ‘{{ counter < 10 }}’ and
    long one: if: {equals: {the: ‘{{ counter }}’, is_not: 10000}}. The clause format is the same as in [checks](checks.md)
  • do: the aciton to be performed. Can be a list of actions or single one.
  • max_cycle: the limit of reductions. Optional default is no limit.
Foreach:iterate data structure
  • in: variable or static list. ITEM variable can be used to access each element of the data structure.
    Data structure can be list, dict or any other python data structure which supports iteration.
  • do: the aciton to be performed. Can be a list of actions or single one.
Examples:

Perform a single echo wile counter is less than 10

loop:
    while:
        if: '{{ counter < 10 }}'
        do:
            echo: {from: '{{ counter + 1 }}', register: {counter: '{{ OUTPUT }}'}}
        max_cycle: 100000

Perform to actions: consume message from kafka and send token via POST http. Do it until server returns passed true in http response.

loop:
    while:
        if:
            equals: {the: '{{ passed }}', is_not: True}
        do:
            - kafka:
                  consume:
                      server: '127.0.0.1:9092'
                      group_id: 'test'
                      topic: 'test_consume_with_timestamp'
                      timeout: {seconds: 5}
                      where:
                          equals: '{{ MESSAGE.timestamp > 1000 }}'
                  register: {token: '{{ OUTPUT.data.token }}'}
            - http:
                post:
                  headers: {Content-Type: 'application/json'}
                  url: 'http://test.com/check_my_token'
                  body: {'token': '{{ token }}'}
                register: {passed: '{{ OUTPUT.passed }}'}

Iterate over iterator variable, produce each element to kafka as json and debug it to file.

loop:
    foreach:
        in: '{{ iterator }}'
        do:
            - kafka:
                  produce:
                      server: '127.0.0.1:9092'
                      topic: 'test_produce_json'
                      data: '{{ ITEM|tojson }}'
            - echo: {from: '{{ ITEM }}', to: '{{ ITEM["filename"] }}.output'}

http - perform http request

class catcher.steps.http.Http(**kwargs)[source]
Input:
<method>:http method. See https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html for details
  • headers: Dictionary with custom headers. Optional
  • url: url to call
  • response_code: Code to await. Use ‘x’ for a wildcard or ‘-‘ to set a range between 2 codes.
    Optional default is 200.
  • body: body to send. Optional.
  • body_from_file: File can be used as data source. Optional.
  • files: send file from resources (only for methods which support it). Optional
  • verify: Verify SSL Certificate in case of https. Optional. Default is true.
  • should_fail: true, if this request should fail, f.e. to test connection refused. Will fail the test if no errors.
  • session: http session name. Cookies are saved between sessions. Optional. Default session is ‘default’.
    If set to null - there would be no session.
  • fix_cookies: if true will make cookies secure if you use https and not secure if you don’t. Optional.
    Default is true. Is useful when you don’t have tls for your test env, but can’t change infra.
  • timeout: number of seconds to wait for response. Optional. Default is no timeout (wait forever)
Files:is a single file or list of files, where <file_param> is a name of request param. If you don’t specify headers ‘multipart/form-data’ will be set automatically.
  • <file_param>: path to the file
  • type: file mime type
Cookies:All requests are run in the session, sharing cookies got from previous requests. If you wish to start new empty session use session. If you don’t want a session to be saved use session: null
Examples:

Put data to server and await 200-299 code

http:
  put:
    url: 'http://test.com?user_id={{ user_id }}'
    body: {'foo': bar}
    response_code: 2XX

Put data to server and await 201-3XX code

http:
  put:
    url: 'http://test.com?user_id={{ user_id }}'
    body: {'foo': bar}
    response_code: 201-3xx

Post data to server with custom header

http:
  post:
    headers: {Content-Type: 'application/json', Authorization: '{{ token }}'}
    url: 'http://test.com?user_id={{ user_id }}'
    body: {'foo': bar}

Post file to remote server

http:
  post:
    url: 'http://test.com'
    body_from_file: "data/answers.json"

SSL without verification

http:
  post:
    url: 'https://my_server.de'
    body: {'user':'test'}
    verify: false

Manual set of json body. tojson will convert ‘var’ to json string

http:
  post:
    url: 'http://test.com?user_id={{ user_id }}'
    body: '{{ var |tojson }}'

Set json by providing json headers and passing python object to body

http:
  post:
    url: 'http://test.com?user_id={{ user_id }}'
    headers: {Content-Type: 'application/json'}
    body: '{{ var  }}'

Send file with a post request

http:
  post:
    url: 'http://example.com/upload'
    files:
        file: 'subdir/my_file_in_resources.csv'
        type: 'text/csv'

Send multiple files with a single post request

http:
  post:
    url: 'http://example.com/upload'
    files:
        - my_csv_file: 'one.csv'
          type: 'text/csv'
        - my_json_file: 'two.json'
          type: 'application/json'

Test disconnected service:

steps:
- docker:
    disconnect:
        hash: '{{ my_container }}'
- http:
    get:
        url: '{{ my_container_url }}'
        should_fail: true

Test correct and incorrect login (clear cookies):

steps:
    - http:
        post:
            url: 'http://test.com/login.php?user_id={{ user_id }}'
            body: {'pwd': secret}
            response_code: 2XX
            session: 'user1'
        name: "Do a login"
    - http:
        get:
            url: 'http://test.com/protected_path'
            response_code: 2XX
            session: 'user1'
        name: "Logged-in user can access protected_path"
    - http:
        get:
            url: 'http://test.com/protected_path'
            response_code: 401
            session: 'user2'
        name: "protected_path can't be accessed without login"

sh - run shell command

class catcher.steps.sh_step.Sh(command=None, path=None, return_code=0, **kwargs)[source]

Run shell command and return output.

Input:
  • command: Command to run.
  • path: Path to be used as a root for the command. Optional.
  • return_code: expected return code. Optional. 0 is default.
Examples:

List current directory

- sh:
    command: 'ls -la'

Determine if running in docker

variables:
    docker: true
steps:
    - sh:
        command: "grep 'docker|lxc' /proc/1/cgroup"
        return_code: 1
        ignore_errors: true
        register: {docker: false}
    - echo: {from: 'In docker: {{ docker }}'}

run another testcase

class catcher.steps.run.Run(ignore_errors=False, _body=None, run=None, include=None, tag=None, variables=None, **kwargs)[source]

Run include on demand

Input:
Include:include name. If contains dot - everything after dot will be considered as tag. In case of multiple dots the last one will be considered as tag.
Variables:Variables to override. Optional
Examples:

Use short form to run sign_up

include:
    file: register_user.yaml
    as: sign_up
steps:
    # .... some steps
    - run: sign_up
    # .... some steps

Run sign_up with username overridden

include:
    file: register_user.yaml
    as: sign_up
steps:
    # .... some steps
    - run:
        include: sign_up
        variables:
            username: test
    # .... some steps

Include sign_up and run all steps with tag register from it. Use dot notation.

include:
    file: register_and_login.yaml
    as: sign_up
steps:
    - run:
        include: sign_up.register

Include one.yaml from main and run only before tag of it. one.before includes two.yaml and runs only run_me tag.

include:
    file: one.yaml
    as: one
steps:
    - run: 'one.before'

include:
    file: two.yaml
    as: run_me
steps:
    - run:
        include: two.run_me
        tag: before
    - echo: {from: '{{ bar }}', to: after.output, tag: after}

steps:
    - echo: {from: '1', to: foo.output, tag: run_me}
    - echo: {from: '2', to: baz.output, tag: two}
    - echo: {from: '3', to: bar.output, tag: three}

stop - stop testcase execution

class catcher.steps.stop.Stop(**kwargs)[source]

Stop a test without error

Input:
If:condition
Examples:

Stop execution if migration was applied.

steps:
    - postgres:
        request:
            conf: '{{ migrations_postgres }}'
            query: "select count(*) from migration where hash = '{{ TEST_NAME }}';"
        register: {result: '{{ OUTPUT }}'}
        tag: check
        name: 'check_migration_{{ TEST_NAME }}'
    - stop:
        if:
            equals: {the: '{{ result }}', is: 1}
    - postgres:
        request:
            conf: '{{ migrations_postgres }}'
            query: "insert into migration(id, hash) values(1, '{{ TEST_NAME }}');"

wait - delay testcase execution

class catcher.steps.wait.Wait(_get_action=None, _get_actions=None, **kwargs)[source]

Wait for some time before the next step

Input:
Days:several days
Hours:several hours
Minutes:several minutes
Seconds:several seconds
Microseconds:several microseconds
Milliseconds:several milliseconds
Nanoseconds:several nanoseconds
For:(list of actions) will repeat them till they all finishes successfully. Will fail if time ends.
Examples:

Wait for 1 minute 30 seconds

wait: {minutes: 1, seconds: 30}

Wait for http to be ready. Will run the http for 5 seconds or till it finishes successfully

wait:
    seconds: 5
    for:
        http:
            put:
                url: 'http://localhost:8000/mockserver/expectation'
                body:
                    httpRequest: {'path': '/some/path'}
                    httpResponse: {'body': 'hello world'}
                response_code: 201

Wait for postgres to be populated

wait:
    seconds: 30
    for:
        - postgres:
              request:
                  conf: '{{ pg_conf }}'
                  query: 'select count(*) from users'
              register: {documents: '{{ OUTPUT }}'}
        - check: {equals: {the: '{{ documents }}', is_not: 0}}