All Projects β†’ nytimes β†’ httptest

nytimes / httptest

Licence: Apache-2.0 license
A simple concurrent HTTP testing tool

Programming Languages

go
31211 projects - #10 most used programming language
Dockerfile
14818 projects
Makefile
30231 projects

Projects that are alternatives of or similar to httptest

github-env-vars-action
πŸš€ GitHub Action for Environment Variables
Stars: ✭ 129 (+207.14%)
Mutual labels:  cicd, github-actions
Cml
♾️ CML - Continuous Machine Learning | CI/CD for ML
Stars: ✭ 2,843 (+6669.05%)
Mutual labels:  cicd, github-actions
github-create-release-action
Github Action that create Github Release automatically
Stars: ✭ 28 (-33.33%)
Mutual labels:  cicd, github-actions
web-extension-boilerplate
The web extension boilerplate help to set up project quickly using typescript, jest, webpack, githook, prettier and github actions
Stars: ✭ 35 (-16.67%)
Mutual labels:  cicd, github-actions
changelog-generator
GitHub Action to generate changelogs, release notes, whatever
Stars: ✭ 95 (+126.19%)
Mutual labels:  cicd, github-actions
Android-CICD
This repo demonstrates how to work on CI/CD for Mobile Apps πŸ“± using Github Actions πŸ’Š + Firebase Distribution πŸŽ‰
Stars: ✭ 37 (-11.9%)
Mutual labels:  cicd, github-actions
Github Pages Deploy Action
Automatically deploy your project to GitHub Pages using GitHub Actions. This action can be configured to push your production-ready code into any branch you'd like.
Stars: ✭ 2,507 (+5869.05%)
Mutual labels:  cicd, github-actions
typescript-container-action-template
πŸ™ Template repository to create a GitHub container action in Node.js with TypeScript
Stars: ✭ 25 (-40.48%)
Mutual labels:  container, github-actions
django-step-by-step
A Django + Vue reference project that focuses on developer tooling and CI/CD + IaC
Stars: ✭ 86 (+104.76%)
Mutual labels:  cicd, github-actions
actions
Our Library of GitHub Actions
Stars: ✭ 49 (+16.67%)
Mutual labels:  cicd, github-actions
up
UP - Ultimate Provisioner CLI
Stars: ✭ 43 (+2.38%)
Mutual labels:  cicd, drone-ci
ci-skip
CI skip comment
Stars: ✭ 35 (-16.67%)
Mutual labels:  drone-ci, github-actions
django-template
The ultimate Django template: production ready Django 3.2 with Docker, HTTPS and CI/CD using Github actions β€ŽοΈβ€πŸ”₯
Stars: ✭ 20 (-52.38%)
Mutual labels:  cicd, github-actions
ssvm-deno-starter
A template project to run Rust functions in Deno through the Second State WebAssembly engine.
Stars: ✭ 50 (+19.05%)
Mutual labels:  github-actions
github-status-updater
Command line utility for updating GitHub commit statuses and enabling required status checks for pull requests
Stars: ✭ 83 (+97.62%)
Mutual labels:  cicd
godot-ci
Docker image to export Godot Engine games. Templates for Gitlab CI and GitHub Actions to deploy to GitLab Pages/GitHub Pages/Itch.io.
Stars: ✭ 316 (+652.38%)
Mutual labels:  github-actions
jacoco-report
Github action that publishes the JaCoCo report as a comment in the Pull Request
Stars: ✭ 31 (-26.19%)
Mutual labels:  github-actions
workflow-tools
CLI tools for GitHub Actions
Stars: ✭ 29 (-30.95%)
Mutual labels:  github-actions
inspr
Inspr is an agnostic application mesh for simpler, faster, and securer development of distributed applications (dApps).
Stars: ✭ 49 (+16.67%)
Mutual labels:  container
action-junit-report
Reports junit test results as GitHub Pull Request Check
Stars: ✭ 103 (+145.24%)
Mutual labels:  github-actions

httptest

Build Status

A simple concurrent HTTP testing tool

Usage

Write a simple test

Create a file tests.yml with the following content:

tests:
  - description: 'root'  # Description, will be printed with test results
    request:             # Request to send
      path: '/'          # Path
    response:            # Expected response
      statusCodes: [200] # List of expected response status codes

Run tests locally

This program is distributed as a Docker image. To run a container locally (under a folder contains tests related yml file):

docker run --rm \
    -v $(pwd)/httpbin.yml:/tests/tests.yml \
    -e "TEST_HOST=example.com" \
    nytimes/httptest

You should see an output similar to this:

passed:  tests.yml | root | /

1 passed
0 failed
0 skipped

Tip: If your test cases have conditions on environment variables (see conditions in full example), remember to include -e "<ENV_VAR>=<value>". e.g.

docker run --rm \
    -v $(pwd)/route-abc-tests.yml:/tests/tests.yml \
    -e "TEST_HOST=www.stg.example.com" \
    -e "TEST_ENV=stg" \
    nytimes/httptest

By default, if your current working directory is $(pwd)/tests, the program will parse all files in $(pwd)/tests recursively. This can be changed using an environment variable.

Run tests in a CI/CD pipeline

This image can be used in any CI/CD system that supports Docker containers.

Examples

  • Drone

    pipeline:
      tests:
        image: nytimes/httptest
        pull: true
        environment:
          TEST_HOST: 'example.com'
  • GitHub Actions

    action "httptest" {
      uses = "docker://nytimes/httptest"
      env = {
        TEST_HOST = "example.com"
      }
    }

Configurations

A few global configurations (applied to all tests) can be specified by environment variables:

  • TEST_DIRECTORY: Local directory that contains the test definition YML or YAML files. Default: tests

  • TEST_HOST: Host to test. Can be overridden by request.host of individual test definitions. If TEST_HOST and request.host are both not set, test will fail.

  • TEST_CONCURRENCY: Maximum number of concurrent requests at a time. Default: 2.

  • TEST_DNS_OVERRIDE: Override the IP address for TEST_HOST. Does not work for request.host specified in YML.

  • TEST_PRINT_FAILED_ONLY: Only print failed tests. Valid values: false or true. Default: false.

Environment variable substitution

This program supports variable substitution from environment variables in YML files. This is useful for handling secrets or dynamic values. Visit here for supported functions.

Example:

tests:
  - description: 'get current user'
    request:
      path: '/user'
      headers:
        authorization: 'token ${SECRET_AUTH_TOKEN}'
    response:
      statusCodes: [200]

Dynamic headers

In addition to defining header values statically (i.e. when a test is written), there is also support for determining the value of a header at runtime. This feature is useful if the value of a header must be determined when a test runs (for example, a header that must contain a recent timestamp). Such headers are specified as dynamicHeaders in the YAML, and each must be accompanied by the name of a function to call and a list of arguments for that function (if required). For example:

dynamicHeaders:
  - name: x-test-signature
    function: myFunction
    args:
      - 'arg1'
      - 'arg2'
      - 'arg3'

The arguments can be literal strings, environment variables, or values of previously set headers (see examples below). The function definitions are in the file dynamic.go and can be added to as necessary. Each function must implement the following function interface:

type resolveHeader func(existingHeaders map[string]string, args []string) (string, error)

These are the functions that are currently supported:

now

Returns the number of seconds since the Unix epoch

Args: none

signStringRS256PKCS8

Constructs a string from args (delimited by newlines), signs it with the (possibly passphrase-encrypted) PKCS #8 private key, and returns the signature in base64

Args:

  • key
  • passphrase (can be empty string if key is not encrypted)
  • string(s)... (any amount of strings, from previously set headers or literal values)

postFormURLEncoded

Sends an HTTP POST request to the given URL (with Content-Type application/x-www-form-urlencoded), returns either the whole response body or a specific JSON element, and treats the remaining arguments as data

Args:

  • url (the URL to send the request to)
  • element (see section on "JSON Query Syntax" below)
  • string(s)... (any amount of strings, from previously set headers or literal values, which will be concatenated and delimited with '&' for the request body)
JSON Query Syntax

The element to return from the JSON response body is specified by a dot-delimited string representing the path to the element. Each part of this string is a single step in that path, and array access is handled by providing a zero-based index. If the element selected has a primitive value, that value is returned. If the element selected is a JSON object or array, that object/array is returned in compact form (insignificant whitespace removed). To return the entire JSON response body, use an empty string.

Examples:
Primitive data
Response body:

{
    "nested": {
        "object": {
            "data": 123
        }
    }
}

Query: 'nested.object.data'
Result: 123

Object
Response body:

{
    "nested": {
        "object": {
            "data": 123
        }
    }
}

Query: 'nested.object'
Result: {"data":123}

Array
Response body:

{
    "nested": {
        "array": [
            "abc",
            "def",
            "ghi"
        ]
    }
}

Query: 'nested.array'
Result: ["abc","def","ghi"]

Array element
Response body:

{
    "nested": {
        "array": [
            "abc",
            "def",
            "ghi"
        ]
    }
}

Query: 'nested.array.1'
Result: def

Whole response
Response body:

Just a normal, non-JSON response

Query: ''
Result: Just a normal, non-JSON response

concat

Concatenates the arguments into a single string

Args:

  • string(s)... (any amount of strings, from previously set headers or literal values, which will be concatenated)

Full test example

Required fields for each test:

  • description
  • request.path

All other fields are optional. All matchings are case insensitive.

tests:
  - description: 'root'                        # Description, will be printed with test results. Required
    conditions:                                # Specify conditions. Test only runs when all conditions are met
      env:                                     # Matches an environment variable
        TEST_ENV: '^(dev|stg)$'                # Environment variable name : regular expression
    skipCertVerification: false                # Set true to skip verification of server TLS certificate (insecure and not recommended)

    request:                                   # Request to send
      scheme: 'https'                          # URL scheme. Only http and https are supported. Default: https
      host: 'example.com'                      # Host to test against (this overrides TEST_HOST for this specific test)
      method: 'POST'                           # HTTP method. Default: GET
      path: '/'                                # Path to hit. Required
      headers:                                 # Headers
        x-test-header-0: 'abc'
        x-test: '${REQ_TEST}'                  # Environment variable substitution
      dynamicHeaders:                          # Headers whose values are determined at runtime (see "Dynamic Headers" section above)
        - name: x-test-timestamp               # Name of the header to set
          function: now                        # Calling a no-arg function to get the header value
        - name: x-test-signature
          function: signStringRS256PKCS8       # Function called to determine the header value
          args:                                # List of arguments for the function (can be omitted for functions that don't take arguments)
            - '${TEST_KEY}'                    # Can use environment variable substitution
            - '${TEST_PASS}'
            - x-test-timestamp                 # Can use values of previously set headers
            - '/svc/login'                     # Can use literals
            - x-test-header-0
            - x-test
        - name: x-test-token
          function: postFormURLEncoded         # Function called to retrieve the header value from an API
          args:
            - '${TOKEN_URL}'                   # The URL to POST to
            - 'results.7.token.id_token'       # The dot-delimited string representing an element to return from the JSON response body; use integers for array elements or '' for the whole response body
            - 'client_secret=${CLIENT_SECRET}' # Can use literals, environment variables, or a combination
            - x-test-timestamp                 # Can use values of previously set headers
            - 'client_id=123'                  # These arguments will be combined to send 'client_secret=${CLIENT_SECRET}&x-test-timestamp&client_id=123' in the body of the request
        - name: authorization
          function: concat                     # Function that concatenates strings, either literals or values from previously set headers
          args:
            - 'Bearer '
            - x-test-token
      body: ''                                 # Request body. Processed as string

    response:                                  # Expected response
      statusCodes: [201]                       # List of expected response status codes
      headers:                                 # Expected response headers
        patterns:                              # Match response header patterns
          server: '^ECS$'                      # Header name : regular expression
          cache-control: '.+'
        notPresent:                            # Specify headers not expected to exist.
          - 'set-cookie'                       # These are not regular expressions
          - 'x-frame-options'
        notMatching:
          set-cookie: ^.*abc.*$                # Specify headers expected to exist but NOT match the given regex
      body:                                    # Response body
        patterns:                              # Response body has to match all patterns in this list in order to pass test
          - 'charset="utf-8"'                  # Regular expressions
          - 'Example Domain'

  - description: 'sign up page'                # Second test
    request:
      path: '/signup'
    response:
      statusCodes: [200]

Development

Run locally

Download package

go get -d -u github.com/nytimes/httptest

Build and run

# In repo root directory
make run

This will run the tests defined in example-tests directory.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].