venom

repository·master·Indexed 22 days ago

https://github.com/ovh/venom

A CLI tool for creating, managing, and running integration tests using YAML-based testsuites. It allows developers to treat tests as code by utilizing various executors—including HTTP, Web, IMAP, AMQP, Couchbase, gRPC, and shell script execution (exec)—and applying assertions to the results.

Tokens
35.1K
Snippets
102
Records
155
Agent score
79%

What's inside venom

  1. Define variables for testsuites

    master

    Venom supports several ways to inject variables into your testsuites. Variables can be strings, lists, or objects.

    1. Command line flag (--var): Best for individual variables.
      • venom run --var="foo=bar"
      • venom run --var='foo_list=["biz","buz"]'
      • venom run --var='foo={"biz":"bar","biz":"barr"}'
    2. Variable definition files (--var-from-file): Best for large sets of variables. The file must be a YAML dictionary.
      • venom run --var-from-file variables.yaml
    3. Environment Variables: Venom looks for environment variables prefixed with VENOM_VAR_.
      • export VENOM_VAR_foo=bar && venom run *.yml

    Precedence: Command line flags override --var-from-file, which overrides environment variables.

    $ venom run --var="foo=bar"
    $ venom run --var='foo_list=["biz","buz"]'
    $ venom run --var='foo={"biz":"bar","biz":"barr"}'
    $ venom run --var-from-file variables.yaml
    $ export VENOM_VAR_foo=bar
    $ venom run *.yml
  2. Skip testcases and teststeps based on assertions

    master

    You can conditionally skip testcase or individual steps using the skip attribute. The skip attribute accepts a list of conditions. If any condition in the skip block is met (evaluates to true), the item is skipped.

    • Testcase level: If a testcase is skipped, its steps are not executed. If all steps within a testcase are skipped, the testcase status is marked as skipped rather than passed or failed.
    • Step level: You can place a skip block inside a step to partially execute a testcase. If the skip condition is met, that specific step is bypassed.
    name: "Skip testsuite"
    vars:
      foo: bar
    
    testcases:
    - name: skip-this
      skip: 
        - foo ShouldBeEmpty
      steps:
      - type: exec
        command: command_not_found
        assertions:
        - result.code ShouldEqual 0
  3. Assert results of IMAP command execution

    master

    Each command execution produces a result object. When multiple commands are executed in one testcase, results are indexed as commands0, commands1, etc.

    Result Structure

    • search: The state of the mail before the command was executed.
    • mail: The state of the mail after the command was executed (only populated for commands that modify content, like append or flag).
    • err: The error message if the command failed.
    • timeseconds: Duration of execution.

    Assertion Syntax Examples

    To assert that a command succeeded and the mail subject changed:

    • result.commands.commands0.err ShouldBeEmpty
    • result.commands.commands0.mail.subject ShouldEqual "New Subject"

    To assert specific flags in a list:

    • result.commands.commands1.mail.flags.flags0 ShouldEqual "Flag1"
    {
      "result": {
        "commands": [
          {
            "search": {
              "mailbox": "INBOX",
              "from": "from@mail-before-command-execution.com",
              "to": "to@mail-before-command-execution.com",
              "subject": "Title of mail BEFORE command execution",
              "body": "Body content of mail BEFORE command execution",
              "flags": [
                "Flag1",
                "Flag2"
              ]
            },
            "mail": {
              "from": "from@mail-after-command-execution.com",
              "to": "to@mail-after-command-execution.com",
              "subject": "Title of mail AFTER command execution",
              "body": "Body content of mail AFTER command execution",
              "flags": [
                "Flag1",
                "Flag2",
                "Flag3"
              ]
            },
            "err": "Error of the command",
            "timeseconds": 1.5
          }
        ]
      }
    }
  4. Use the search field to target specific emails

    master

    The search field is used by most commands to identify which email to act upon. It retrieves and returns the first email matching the criteria.

    Important: Search criteria are regular expressions. You must escape special characters (e.g., use \[ instead of [).

    Available search keys:

    • mailbox: The mailbox name to search in.
    • uid: The specific UID to search for.
    • from: Regex for the "From" header.
    • to: Regex for the "To" header.
    • subject: Regex for the "Subject" header.
    • body: Regex for the email body.
    • flags: (Implicitly used in results) The list of flags on the mail.
    search:
      mailbox: testBox
      uid: 1
      from: .*@your-domain.localhost
      to: you@company.tld
      subject: Title of mail with \*
      body: .*a body content.*
  5. Use logical operators in assertions

    master

    To perform complex validation, you can use logical operators within the assertions block. Supported operators are:

    • and (implicit)
    • or
    • xor

    Operators can be nested to create complex logic trees.

    - name: Assertions operators
      steps:
      - script: echo 1
        assertions:
          - or:
            - result.systemoutjson ShouldEqual 1 
            - result.systemoutjson ShouldEqual 2
          # Nested operators
          - or:
            - result.systemoutjson ShouldBeGreaterThanOrEqualTo 1
            - result.systemoutjson ShouldBeLessThanOrEqualTo 1
            - or:
              - result.systemoutjson ShouldEqual 1
  6. How TestSuites and TestCases are structured

    master

    In venom, a TestSuite is a collection of TestCases defined in a single YAML file. Each TestSuite contains multiple TestCases, and each TestCase consists of an ordered set of steps. Each step is driven by an executor (the type field) that defines the behavior (e.g., executing a script, making an HTTP request, or querying a database).

    TestSuite Structure

    A typical YAML structure includes:

    • name: Title of the suite.
    • description: Markdown description.
    • vars: Testsuite-level variables.
    • testcases: A list of testcase objects.

    Each testcase contains:

    • name: Name of the testcase.
    • steps: A list of steps, where each step can have a type, script, assertions, vars, and retry logic.
    name: Title of TestSuite
    description: A detailed description of the TestSuite, in markdown.
    testcases:
    - name: TestCase with default value, exec cmd. Check if exit code != 1
      steps:
      - script: echo 'foo'
        type: exec
    
    - name: Title of First TestCase
      steps:
      - script: echo 'foo'
        assertions:
        - result.code ShouldEqual 0
      - script: echo 'bar'
        assertions:
        - result.systemout ShouldNotContainSubstring foo
        - result.timeseconds ShouldBeLessThan 1
  7. Understand RabbitMQ execution types in Venom

    master

    The RabbitMQ executor supports three distinct execution modes, which you select using the clientType parameter in your YAML testcase steps:

    1. publisher: Sends a message to a specific queue or an exchange.
    2. subscriber: Binds to a queue or an exchange (using a routingKey) and waits to consume messages.
    3. client: Performs a request/reply pattern. It publishes a message and waits for a response message on the RabbitMQ reply-to queue.
  8. Configure MQTT Client Types in Venom

    master

    When configuring the MQTT executor in Venom, you must specify a ClientType. The available options are:

    • publisher: Used to send messages to MQTT topics.
    • subscriber: Used to listen for messages on MQTT topics.
    • persistent_queue: Creates a persistent session by setting the session_clean property. This allows subsequent subscriber steps to retrieve data that was sent while the client was disconnected.

    Important for Persistent Queues: To ensure the broker tracks state correctly across different steps, the persistent_queue step and the subscriber step must use the same client id. Additionally, you should use the persistSubscription property (set to true or false) to request or release the persistent topic subscription. Remember to remove the topic registration once your sequence is complete.

  9. Use `Must` keywords for required assertions

    master

    Every built-in assertion keyword has a Must counterpart. Using a Must keyword creates a required passing assertion. If a Must assertion fails, Venom will prevent the execution of any remaining steps in that specific testcase.

    Example:

    - steps:
      - type: exec
        script: exit 1
        assertions:
          - result.code MustEqual 0
      # Remaining steps in this context will not be executed
  10. Iterate over data using the range attribute

    master

    The range attribute allows you to iterate over different data types within a step. During iteration, the following contextual variables are available:

    • Arrays ([]interface{}): Iterates over each value. Use .index (or .key) for the current index and .value for the item.
    • Maps (map[string]interface{}): Iterates over keys. Use .index for the current index, .key for the current key, and .value for the current value.
    • Integers (int): Performs the target step n times. Use .index (or .key or .value) for the current iteration index.
    • Templated Strings: Strings that resolve to one of the above types (e.g., from vars or previous step results).
    - name: range with hardcoded array
      steps:
      - type: exec
        range:
          - actual: hello
            expected: hello
          - actual: world
            expected: world
        script: echo "{{.value.actual}}"
        assertions:
        - result.code ShouldEqual 0
        - result.systemout ShouldEqual "{{.value.expected}}"