Git Product home page Git Product logo

tomato's Introduction

๐Ÿ… tomato - functional testing tool kit

CircleCI Go Report Card GoDoc codecov.io

Tomato is a language agnostic testing tool kit that simplifies the acceptance testing workflow of your application and its dependencies.

Using godog and Gherkin, tomato makes behavioral tests easier to understand, maintain, and write for developers, QA, and product owners.

Features

  • Cucumber Gherkin feature syntax
  • Support for MySQL, MariaDB, and PostgreSQL
  • Support for messaging queues (RabbitMQ, NSQ)
  • Support for mocking HTTP API responses
  • Additional resources resources

Getting Started

Set up your tomato configuration

Tomato integrates your app and its test dependencies using a simple configuration file tomato.yml.

Create a tomato.yml file with your application's required test resources:

---

# Randomize scenario execution order
randomize: true

# Stops on the first failure
stop_on_failure: false

# All feature file paths
features_path:
    - ./features
    - check-status.feature

# List of resources for application dependencies
resources:
    - name: psql
      type: postgres
      options:
        datasource: {{ .PSQL_DATASOURCE }}

    - name: your-application-client
      type: httpclient
      options:
        base_url: {{ .APP_BASE_URL }}

Write your first feature test

Write your own Gherkin feature (or customize the check-status.feature example below) and place it inside ./features/check-status.feature:

Feature: Check my application's status endpoint

  Scenario: My application is running and active
    Given "your-application-client" send request to "GET /status"
    Then "your-application-client" response code should be 200

Run tomato

Using docker-compose

Now that you have your resources configured, you can use docker-compose to run tomato in any Docker environment (great for CI and other build pipelines).

Create a docker-compose.yml file, or add tomato and your test dependencies to an existing one:

version: '3'
services:
  tomato:
    image: quay.io/tomatool/tomato:latest
    environment:
      APP_BASE_URL: http://my-application:9000
      PSQL_DATASOURCE: "postgres://user:password@postgres:5432/test-database?sslmode=disable"
    volumes:
      - ./tomato.yml:/config.yml # location of your tomato.yml
      - ./features/:/features/   # location of all of your features

  my-application:
    build: .
    expose:
      - "9000"

  postgres:
    image: postgres:9.5
    expose:
      - "5432"
    environment:
            POSTGRES_USER: user
            POSTGRES_PASSWORD: password
            POSTGRES_DB: test-database
    volumes:
      - ./sqldump/:/docker-entrypoint-initdb.d/ # schema or migrations sql

Execute your tests

docker-compose up --abort-on-container-exit

Install latest stable version

curl https://raw.githubusercontent.com/tomatool/tomato/master/install.sh | sh

Install latest master

Install tomato by grabbing the latest stable release and placing it in your path, or by using go get

go get -u github.com/tomatool/tomato

Executing tomato

Now run tomato:

tomato tomato.yml

Resources

Resource are the objects that are going to be used for steps in the scenario. They are listed under the resources key in the pipeline configuration.

List of available resources

tomato's People

Contributors

alileza avatar jefarr avatar robertgzr avatar snagles avatar soverdrive avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

tomato's Issues

Use tomato.yml to orchestrate dependency resources

Is your feature request related to a problem? Please describe.
There is a lot of overlap between the tomato.yml file and docker-compose file

Describe the solution you'd like
Maybe we could explore a way to integrate the two with the tomato.yml outputting a docker-compose (or k8s cluster configuration, or any other dependency orchestrator) file whenever you update it so you only have to maintain one file

db/sql: show table data when rows not found

Then "psql" table "plan" should look like
      | id | name    |
      | 1  | antoni  |

on table should look like, when rows not found. would be nice to show what's the table looks like on that point.

Remove Dockerfile.test

for simplicity, rather than having multiple duplicated Dockerfile, merge both dockerfile into 1, and use docker build stage to separate test image & production image

for e. g:

FROM golang AS builder
FROM golang AS test
# copy test binary from builder
FROM golang AS tomato
# copy production binary from builder

Potential import collision: import path should be "github.com/nsqio/go-nsq", not "github.com/bitly/go-nsq"

Background

I find that github.com/nsqio/go-nsq and github.com/bitly/go-nsq coexist in this repo๏ผš
https://github.com/tomatool/tomato/blob/main/go.mod ๏ผˆLine 9&22๏ผ‰

github.com/bitly/go-nsq v1.0.7
github.com/nsqio/go-nsq v1.0.7 // indirect

Thatโ€™s because the "github.com/bitly/go-nsq" has already been redirected to "github.com/nsqio/go-nsq". When you use the old path "github.com/bitly/go-nsq" to import the go-nsq, github automatically directed to github.com/nsqio/go-nsq, returned the repo github.com/nsqio/go-nsq, and reintroduces github.com/nsqio/go-nsq through the import statements "import github.com/nsqio/go-nsq" in the go source file of nsqio/go-nsq.

https://github.com/nsqio/go-nsq/blob/v1.0.7/config_flag_test.go

package nsq_test
import (
	"flag"
	"github.com/nsqio/go-nsq"
)

This will work in isolation, bring about potential risks and problems.

Solution

Replace all the old import paths, change "github.com/bitly/go-nsq" to "github.com/nsqio/go-nsq".
Where did you import it: https://github.com/tomatool/tomato/search?q=github.com%2Fbitly%2Fgo-nsq&unscoped_q=github.com%2Fbitly%2Fgo-nsq

Consider wiremock as http/server resource

Is your feature request related to a problem? Please describe.
In a lot of cases integration test that involving external services, are using wiremock. Even though, tomato built in http/server also able to solve this problem, having support for wiremock integration would makes it easier for people to integrate.

Describe the solution you'd like
Implement wiremock client api that implement http/server interface, and use it as we're driver for another resource

    - name: tomato-http-server
      type: http/server
      ready_check: true
      params:
         driver: wiremock
         host: [wiremock_endpoint]

debug mode

add debug mode when running the test, show verbose log of what tomato is doing.

Level 1 : handler
Level 2 : handler, resource

examples :

resource "psql" connected to "127.0.0.1:5432" using driver "postgres"
"psql" exec query "INSERT INTO"
"psql" query row "SELECT COUNT(*) FROM"

Add AWS Resource

Using localstack I think we could implement functional testing of applications that depend on AWS resources

gives more informative error message if action is not exist

error message when action is not available at the moment looks like:

2 scenarios (2 failed, 1 undefined)
5 steps (2 failed, 1 undefined, 2 skipped)
8.374339ms

You can implement step definitions for undefined steps with these snippets:

func responseHeaderShouldBe(arg1, arg2, arg3 string) error {
        return godog.ErrPending
}

func FeatureContext(s *godog.Suite) {
        s.Step(`^"([^"]*)" response header "([^"]*)" should be "([^"]*)"$`, responseHeaderShouldBe)
}

we'd like to have more brief & informative error message that tells the user which action is wrong, e.g:

Step action is unavailable : 
    Given "cli" response headers "Content-Type" should be "application/json"

would even nicer if there's suggestion

Enable creating fully defined stubs via JSON with wiremock resource

Is your feature request related to a problem? Please describe.
I would like to use wiremock to check for request body patterns and provide an XML response body defined in a file.

At the moment, wiremock has a rigid setup only allowing request counting (no matching possible) and only inline JSON body. Wiremock itself provides many options via its JSON api (http://wiremock.org/docs/stubbing/) which are also easy to use and have powerful documentation. I see no reason to limit it for Tomato users.

Describe the solution you'd like
I would like to be able to define, in my feature file, the JSON that would define the whole mapping for wiremock, like this:

    "request": {
        "method": "GET",
        "url": "/some/thing"
    },
    "response": {
        "status": 200,
        "body": "Hello world!",
        "headers": {
            "Content-Type": "text/plain"
        }
    }
}

Describe alternatives you've considered
I considered building tests in pure Go and using wiremock separately, but I like how Tomato integrates with rabbitmq and I would like to keep using it. I also tried setting up mappings for wiremock separately, by putting JSON files in mapping directory, but as Tomato resets wiremock after each scenario, this did not work out.

Additional context
I think one possible solution would be to add an additional step for wiremock, something along the lines of Given wiremock with JSON mapping or similar. Then, this whole JSON is POSTed to wiremock JSON api.

I think this addition would be very powerful for users who use Tomato with wiremock as this would enable full stubbing features of wiremock and require little coding in the Tomato itself, as wiremock has stubbing nicely built in already.

create docs generator

to be able to have consistent and good documentation, would be nice to have docs generator that reflected directly to the app

Support schema definitions in the database type

Is your feature request related to a problem? Please describe.
Define database schema using Gherkin clauses.

Describe the solution you'd like
Support for sql schema definitions inside the feature test files.

Describe alternatives you've considered
Migrations as part of the database setup/teardown process. Support inside the database resource

Support different HTTP methods in http/server

Is your feature request related to a problem? Please describe.
Currently http/server using wiremock is hardcoded to GET requests, when we should support all http methods.

Describe the solution you'd like
Support all HTTP methods such as POST, PUT, etc.

Add Redis Resource

Redis is frequently used cache storage, so it will be good to have it as one of the resources.

Cannot set nullable varchar field to empty string

Describe the bug
Unable to explicitly set a varchar field to an empty string. When setting to an empty string, the value is converted to null.

To Reproduce
Steps to reproduce the behavior:
Schema

CREATE TABLE table (
	"id" SERIAL PRIMARY KEY,
	"email" VARCHAR(255),
)

Feature

  Given set "db" table "table" list of content
      | id    | email |  
      |  1    |           |

Expected behavior
Defined field with empty string value.

Additional context
Add any other context about the problem here.

Add toxiproxy resource

It could be helpful to generate timeout/disconnection behavior for apps using tomato. There seem to be a few libraries that we could use as a proxy between the connections and then manipulate them using tomato.

github.com/Shopify/toxiproxy seems promising and has an easy to use go client

Shell resource prefix feature

Is your feature request related to a problem? Please describe.
At the moment each time using shell resource, you'd need to specify full shell command, for example

Scenario 1: check pod
   Given "bash" execute "kubectl get pods"

when most likely we'd use the same command over and over for the scenario (in this case kubectl)

Describe the solution you'd like
add prefix params that automatically prepended to all command executed by the shell resource, like :

resources:
  - name: kubectl
    type: shell
    params:
        prefix: "kubectl"

this way, you would use the resource this way instead

Scenario 1: check pod
   Given "kubectl" execute "get pods"

Improve config consistency

Is your feature request related to a problem? Please describe.
At the moment we have some config passed as a cli flag, and some in config file.

Describe the solution you'd like
Move all cli flag config to be able to be configured also from config file

Consider generating `dictionary.yml` from handler package

Is your feature request related to a problem? Please describe.
Writing go code based/generated from yml file feels wrong, since it's a go application. Go (executable binary) should be the source of truth.

Describe the solution you'd like
It would be nice to have dictionary.yml generated from handler package itself, maybe consider using how godoc.org steal from code comments to get detailed documentation.

Describe alternatives you've considered
Re-structure the handler packages to be godoc friendly, that way, the handler/action documentation can come from godoc

Show beautiful error mismatch message

due to user experience, error message from tomato should give just enough information of

  • what is happening?
  • what cause it?
  • how can you fix it?
  • and some context

Trim request body httpclient resource

Describe the bug
When sending request with payload, httpclient is not trimming the request body, so

server will be able to read this properly

Given "http-cli" send request to "POST /api/v1" with body
        """
myparams=booyah
        """

but not this

Given "http-cli" send request to "POST /api/v1" with body
        """
               myparams=booyah
        """

Expected behavior
those 2 example above should behave the same way

MySQL Bit Column support

Is your feature request related to a problem? Please describe.
Unable to interact with MySQL bit column type

Describe the solution you'd like
Add a function that handle bit column type something like

b'1' & b'0' or bit::0 &bit::1

Shell resource new function

Is your feature request related to a problem? Please describe.
There is no way we can check exit code from executed command in shell resource

Describe the solution you'd like
Would be nice to add a new function to get latest exit code from executed command

https://github.com/tomatool/tomato/blob/master/handler/shell/shell.go#L10

something like

type Resource interface {
	resource.Resource

	Exec(command string, arguments ...string) error
	ExitCode() (int, error)
	Stdout() (string, error)
	Stderr() (string, error)
}

Prefix tags / releases with `v`

Is your feature request related to a problem? Please describe.
Currently there is no version transparency when installing tomato. The last acknowledged version number is v1.1.0 https://pkg.go.dev/github.com/tomatool/tomato?tab=overview. This makes readability around what version we have harder.

image

As you can see here, it picks up the last acknowledged version, then appends the date and commit for the latest release.

Describe the solution you'd like
I could be lost, but I believe v prefixing the tags will make this small problem go away.

Describe alternatives you've considered
I have not considered any, happy to hear if there are.

Additional context
N/A

Add support for comparing JSON column on PostgreSQL driver

In the meantime, comparing JSON column for db/sql postgres driver would throw an error. It would be nice to have a way, to make it possible.

Then "tomato-mysql" table "customers" should look like
        | customer_id | name    | metadata                   |
        | 1           | cembri  | {"ip_address":"127.0.0.1"} |

Standardize resource definition

Is your feature request related to a problem? Please describe.
When the RabbitMQ resource is called with New(), it executes an amqp dial call, while all other resources do not attempt a connection until Ready() or an action has been called on the resource.

Describe the solution you'd like
For consistency, I think we should define the resource interface and keep all logic similar across all resources.

New - construct a configuration for a given resource
Open - build and access resource implementation
Ready - attempt action execution to verify resource readiness
Reset - clean up state
Close - destroy any relation with given resource

Add empty table feature for `db/sql` resource

Would be nice if we can have empty table, or even empty all tables feature for steps in scenario

example :

Then "tomato-mysql" empty table "customers"
Then "tomato-postgres" empty table "*"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.