Giter Club home page Giter Club logo

gonkey's People

Contributors

33r01b avatar alexey19 avatar architectv avatar avgur avatar c1rno avatar cdayz avatar chistopat avatar codercms avatar covid-17 avatar dariakameneva avatar dependabot[bot] avatar droppoint avatar fetinin avatar hibooboo2 avatar justskiv avatar keyclaim avatar leorush avatar luza avatar maximdanilchenko avatar nikolayoskin avatar oburova avatar rsimkin avatar sashamelentyev avatar smolevich avatar svzhl avatar vitkarpenko 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

gonkey's Issues

Assert response headers and cookies

Hi,

is it possible to assert the headers and cookies in the response? Using response I can only define a status code and a body.

Thanks for any hints!

Doesn't work with Windows/Не работает под Windows

При попытке собрать под Windows возникает такая ошибка:

..\vendor\github.com\lamoda\gonkey\cmd_runner\cmd_runner.go:23:41: unknown field 'Setpgid' in struct literal of type syscall.SysProcAttr
..\vendor\github.com\lamoda\gonkey\cmd_runner\cmd_runner.go:43:16: undefined: syscall.Getpgid
..\vendor\github.com\lamoda\gonkey\cmd_runner\cmd_runner.go:48:13: undefined: syscall.Kill

Это связано с тем, что в Windows нет поддержки групп процессов и сигналов.
Как вариант решение это создать файл с постфиксом _windows - cmd_runner_windows.go:

package cmd_runner

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strings"
	"time"
)

func CmdRun(scriptPath string, timeout int) error {
	//by default timeout should be 3s
	if timeout <= 0 {
		timeout = 3
	}
	cmd := exec.Command(strings.TrimRight(scriptPath, "\n"))
	cmd.Env = os.Environ()

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}

	if err := cmd.Start(); err != nil {
		return err
	}

	done := make(chan error, 1)
	go func() {
		done <- cmd.Wait()
	}()

	select {
	case <-time.After(time.Duration(timeout) * time.Second):
		// Kill process
		if err := cmd.Process.Kill(); err != nil {
			return err
		}
		fmt.Printf("Process killed as timeout(%d) reached\n", timeout)
	case err := <-done:
		if err != nil {
			return fmt.Errorf("process finished with error = %v", err)
		}
		log.Print("Process finished successfully")
	}

	// Print log
	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		m := scanner.Text()
		fmt.Println(m)
	}

	return nil
}

А в оригинальном cmd_runner.go указать в самом верху:

// +build !windows

Можно ли организовать эти изменения в инструменте?

Не работает выполнение sql запроса после теста для MySQL

При выполнении запроса в БД MySQL:

dbQuery:
    SELECT my_field FROM my_table WHERE id = 1
dbResponse:
    - '{"my_field": "123456"}'

Получаю ошибку:
Error 1305: FUNCTION my_db.row_to_json does not exist
Я думаю это связано с тем что при конструировании SQL-запроса(функция newQuery: github.com/lamoda/[email protected]/checker/response_db/response_db.go:139) не учитывается DBType.

Возможность имитации ошибок сети в моках

Необходима функциональность как в wiremock - https://wiremock.org/docs/simulating-faults/
У нас уже есть возможность указывать Status и Body.
Необходимо добавить стратегии вида:

How I can send file by POST?

How I can send file(s) with json fields by POST? (Как отправить файл вместе с json полями POST-ом)

Возможность использовать afterScript для выполнения действий после HTTP-запроса

Я бы хотел добавить afterScript по аналогии с beforeScript для того, что бы обновить materialised views перед dbQuery. На данный момент обновить их можно использовать beforeScript и dbQuery во втором тесте, но это костыль и делает тесты менее очевидными.

Multiple DB queries

At the moment only one dbQuery statement is supported per test case. It would be nice to query multiple independent statements or run dbQuery alone in a separate test case with no HTTP request emitted.

The current workaround is to run a single big query with multiple joins but it has some drawbacks.

  dbQuery:
    SELECT i.id, i.name, p.value
    FROM items i
    LEFT JOIN properties p ON p.item_id = i.id;

  dbResponse:
    - '{"id":"123","name":"test_name","value":"property1"}'
    - '{"id":"123","name":"test_name","value":"property2"}'

You can see that id and name values should be repeated in the results.

The situation becomes worse if a test case requires to check the data in two or more completely independent tables. Using join for this is misleading for a reader of test as the tables are orthogonal.

Поддержка работы с Redis или его мокирование

В случае если это будет мок предлагается использовать https://github.com/rafaeljusto/redigomock

Предполагается, что на уровне проекта при необходимости будет инициализировано замоканное соединение redigomock.NewConn()

Можно расширить параметры запуска тестов этим соединением:

runner.RunWithTesting(t, &runner.RunWithTestingParams{
 ..
 RedisMock:   r
})

Выполнять очистку конфигурации мока после каждого теста через redigomock.Clear()
Добавить возможность описания конфигурации мока через yaml-сценарий по соответствующим нотациям нотациям.
Например

redisMock:
 command:
  GETPERSON:
   calls: 1
   args: person:1
   responseOk: >
    {
        "name": "Mr. Johson",
        "age":  "42",
      }
  GETADDRESS:
   calls: 2
   args: person:2
   responseError: Simulated error!

После выполнения теста мок должен возвращать список ошибок:
в каких ручках количество вызовов не соответствует ожидаемому (по аналогии с func (m *Mocks) EndRunningContext() []error)

Альтернативой может быть интерфейс позволяющий загружать данные в Redis и выполнять очистку, а также checker позволяющий проверить наличие данных.

Неправильно работает режим IgnoreArraysOrdering

Один из наших тестов фейлится из-за того, что сравнение с IgnoreArraysOrdering периодически неправильно производит сравнение. Проще всего воспроизвести, если в тестах "https://github.com/lamoda/gonkey/blob/master/compare/compare_test.go" поставить :

var complexJson1 = `
{
  "data": [
    {
      "name": "n222"
    },
    {
      "name": "n111"
    }
  ]
}
`
var complexJson2 = `
{
  "data": [
    {
      "message": "m555",
      "name": "n222"
    },
    {
      "message": "m777",
      "name": "n111"
    }
  ]
}
`

и в CompareParams прописать опцию IgnoreArraysOrdering: true.

Ну и в тесте поправить TestCompareEqualComplexJson:

func TestCompareEqualComplexJson(t *testing.T) {
	var json1, json2 interface{}
	json.Unmarshal([]byte(complexJson1), &json1)
	json.Unmarshal([]byte(complexJson1), &json2)          <----- тут прописать complexJson2
	errors := Compare(json1, json2, CompareParams{})
	if len(errors) != 0 {
		t.Error(
			"must return no errors",
			fmt.Sprintf("got result: %v", errors),
		)
		t.Fail()
	}
}

Необходимо добавить поддержку regexp в requestConstraints.bodyMatchesXML

Как оказалось requestConstraints.bodyMatchesXML не позволяет проверять вложенный объект и не поддерживает regexp. Таким образом не получается избежать непредсказуемых данных.

Решение:
В requestConstraints.bodyMatchesJSON уже есть поддержка regexp.
Необходимо добавить ее и в стратегию bodyMatchesXML.

Variables usage

Is it possible to use inserted row id from the db fixture inside the web request test?
Can you, please, provide example how to insert record into db and than test http request to fetch data by inserted id?

"calls" constraint of mock in not always cleared before next test run

How to reproduce:

  1. Execute test with mock with "calls" constraint
...
 mocks:
    someservice:
      strategy: uriVary
      uris:
         v1/test:
          calls: 1
          strategy: file
          filename: responses/test.json
...
  1. After that run next test without mocks.
    It will fail with error:

mock someservice: at path $.uriVary.v1/test: number of calls does not match: expected 1, actual 0

Добавить возможность проверять списки с неизвестным заранее количеством элементов

Сейчас Gonkey умеет проверять массивы только на точное соответствие, т.е. набор элементов строго фиксирован. Но некоторых случаях мы не можем точно знать это количество, либо оно очень большое.

Нужно подумать и добавить возможность проверять общий случай.

Пример ответа сервера:

{
        "status": "OK",
        "url": ["https://some-url-1.com", "https://some-url-2.com"]
}

Проблемы:

  1. Список может быть большим, и нет смысла описывать его целиком в кейсе.
    Решение: проверять элементы по общему паттерну (regexp) и/или проверять их количество

  2. Порядок элементов может быть не детерминирован. К примеру, в кейсе список описан так: ["value_1", "value_2"], и если от сервера придет ["value_2", "value_1"], тест сфэйлится.
    Решение: добавить возможность проверки наличия всех элементов, не зависимости от порядка.

Крмое того, могут оказаться полезными проверки included / not included, что бы проверять, что в списке есть или отсутствует конкретные элемент.

Возможность указывать в качестве request/response файл

Чтобы не ломать обратную совместимость можно добавить новые нотации, либо все же переработать старые.
Эта фича имеет смысл после реализации #142.
Тогда можно будет избавиться от больших json внутри yaml-сценария.

requestFromFile:
  file: some_request.json
  overrideParams:
    order[0].amount: 1000.01 
respinseFromFile:
  file: some_respinse.json
  overrideParams:
    order[0].amount: 1000.01 

Возможность помечать отдельный тест статусом skipped/broken etc

Нужно больше контроля над запуском тестов.
Возможность запускать отдельный файл хорошо, но куда удобней иметь переключатель в самом тесте.

Предлагаю также помечать тесты которые мы хотим пропустить этими же статусами и не выполнять их.
Так мы сможем

  • broken если в текущий момент их нельзя удалить но нужно пропускать
  • skipped если нам нужно пропустить тест

Мы пробрасывает результат в поле status в AllureReport и там уже предполагается набор состояний
tab_graphs

Поддержка regExp в dbResponse

Добавить возможность проверки отдельных значений в dbResponse по регулярке.
Например, чтобы была возможна такая конструкция:

  dbResponse:
    - '{
          "city": "Новгород",
          "revision_id": "$matchRegexp(^[0-9a-fA-F]{8}$)"
       }'
    - '{
          "city": "Москва",
          "revision_id": "$matchRegexp(^[0-9a-fA-F]{8}$)"
       }'

Slow mocks shutdown in Go 1.15

In Go 1.15 behavior of http.Server.Shutdown changed and now server waits for all listeners to disconnect.

// go/1.15/libexec/src/net/http/server.go:2699
...
ticker := time.NewTicker(shutdownPollInterval) // 500 ms
defer ticker.Stop()
for {
	if srv.closeIdleConns() && srv.numListeners() == 0 { // for some reason this is always false first time
		return lnerr
	}
	select {
	case <-ctx.Done():
		return ctx.Err()
	case <-ticker.C:  // we always wait here half a second
	}
...

For some reason, on mock shutdown we always still have some active connections and shutdown takes about 500ms. And since we shutdown all mocks synchronously with a lot of mocks we wait for tests to finish for up to 18 seconds.

Does anyone else have this issue?

As a solution we can close each mock server in a separate goroutine, that should reduce wait time for us from 18s to 500ms.

Добавить в моки возможность давать ответ в зависимости от body/query запроса

Проблема: при использовании стратегии sequence, если запросы во внешнюю систему выполняются параллельно невозможно предсказать какой ответ должен вернуть мок. Стратегия позволяет лишь обозначить порядок ответов.

Решение: добавить в стратегию sequence флаг basedOnRequest, по которому мок будет давать ответ только если успешно пройден requestConstraints. В таком случае каждый степ становится уникальным и при получении запроса мок проверяет его по всем requestConstraints. Ответ берется из первого пройденного.

Алтернатива с названием: оформить как отдельную стратегию basedOnRequest

Поддержка проверки логов приложения

Реализовать интерфейс через который можно будет передавать/получать/проверять логи приложения в Gonkey.
Логи как и моки должны очищаться в конце теста.
Реализовать logger checker, который будет проверять содержимое и тип сообщения в логах (необходимо проработать стратегии проверки).
Реализовать нотации для yaml-тетсов.

Добавить проверку value в queryMatches моков по regexp

Также как мы проверяем значения полей в jsonBody будет удобно проверять и отдельные значения в query.
Например, чтобы была возможна такая конструкция ?jsonrpc=2.0&order_nr=$matchRegexp(^[0-9]{9}$)

Data race при прогонке тестов

При прогонке тестов возник data-race. Версия gonkey v1.12.0.

Привожу записи из лога:

build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m WARNING: DATA RACE
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m Write at 0x00c000609890 by goroutine 40:
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m github.com/lamoda/gonkey/mocks.(*ServiceMock).ServeHTTP()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /go/pkg/mod/github.com/lamoda/[email protected]/mocks/service_mock.go:64 +0x1f3
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m net/http.serverHandler.ServeHTTP()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /usr/local/go/src/net/http/server.go:2878 +0x89a
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m net/http.(*conn).serve()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /usr/local/go/src/net/http/server.go:1929 +0x12e4
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m net/http.(*Server).Serve- dwrap- 82()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /usr/local/go/src/net/http/server.go:3033 +0x58
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m Previous read at 0x00c000609890 by goroutine 62:
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m github.com/lamoda/gonkey/mocks.(*ServiceMock).EndRunningContext()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /go/pkg/mod/github.com/lamoda/[email protected]/mocks/service_mock.go:88 +0x84
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m github.com/lamoda/gonkey/mocks.(*Mocks).EndRunningContext()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /go/pkg/mod/github.com/lamoda/[email protected]/mocks/mocks.go:85 +0x124
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m github.com/lamoda/gonkey/runner.(*Runner).executeTest()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /go/pkg/mod/github.com/lamoda/[email protected]/runner/runner.go:180 +0x995
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m github.com/lamoda/gonkey/runner.(*Runner).Run()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /go/pkg/mod/github.com/lamoda/[email protected]/runner/runner.go:75 +0x1f0
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m github.com/lamoda/gonkey/runner.RunWithTesting()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /go/pkg/mod/github.com/lamoda/[email protected]/runner/runner_testing.go:98 +0x10fc
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m stash.lamoda.ru/payment/payment-gate/tests/gonkey.TestRunner.Run()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /app/tests/gonkey/test_runner.go:101 +0xbb9
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m stash.lamoda.ru/payment/payment-gate/tests/gonkey.TestRefundNeg()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /app/tests/gonkey/commandbox_test.go:49 +0x204
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m testing.tRunner()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /usr/local/go/src/testing/testing.go:1259 +0x22f
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m testing.(*T).Run- dwrap- 21()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /usr/local/go/src/testing/testing.go:1306 +0x47
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m Goroutine 40 (running) created at:
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m net/http.(*Server).Serve()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /usr/local/go/src/net/http/server.go:3033 +0x847
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m github.com/lamoda/gonkey/mocks.(*ServiceMock).StartServerWithAddr- dwrap- 3()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /go/pkg/mod/github.com/lamoda/[email protected]/mocks/service_mock.go:40 +0x58
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m Goroutine 62 (running) created at:
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m testing.(*T).Run()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /usr/local/go/src/testing/testing.go:1306 +0x726
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m testing.runTests.func1()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /usr/local/go/src/testing/testing.go:1598 +0x99
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m testing.tRunner()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /usr/local/go/src/testing/testing.go:1259 +0x22f
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m testing.runTests()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /usr/local/go/src/testing/testing.go:1596 +0x7ca
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m testing.(*M).Run()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m /usr/local/go/src/testing/testing.go:1504 +0x9d1
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m main.main()
build 01-Apr-2022 15:14:49 [36mpayment-gate-test |[0m _testmain.go:149 +0x324

В методе (*mocks.ServiceMock).ServeHTTP() происходит перезапись слайса m.errors.

func (m *ServiceMock) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	m.Lock()
	defer m.Unlock()

	if m.mock != nil {
		errs := m.mock.Execute(w, r)
		m.errors = append(m.errors, errs...)
	}
}

А в методе (*mocks.ServiceMock).EndRunningContext(), происходит чтение из m.errors слайса. И оно мьютексом не закрыто. Получается race condition.

func (m *ServiceMock) EndRunningContext() []error {
	errs := append(m.errors, m.mock.EndRunningContext()...)
	for i, e := range errs {
		errs[i] = &Error{
			error:       e,
			ServiceName: m.ServiceName,
		}
	}
	return errs
}

Http only endpoint testing

In case destination service hosted using https endpoint it is impossible to use gonkey command line, because gonkey console uses hard coded http schema.

Start mockserver with definition at startup

Currently, mocks can only be defined on a per test basis. We have a service that connects to an external endpoint (elasticSearch) on startup, before the http server is started. Our service cannot start as m := mocks.NewNop("elastic") returns 204 for all requests on this mock endpoint and it thinks that elasticsearch is not available.

Is it possible to start a mock server with a definition before the actual tests run?

Предупреждать в случае если allure-отчет не создается

Если в энвах нет GONKEY_ALLURE_DIR то отчет не создается. Необходимо сообщать об этом при старте теста.

if os.Getenv("GONKEY_ALLURE_DIR") != "" {
allureOutput := allure_report.NewOutput("Gonkey", os.Getenv("GONKEY_ALLURE_DIR"))
defer allureOutput.Finalize()
r.AddOutput(allureOutput)
}

Также транслировать предупреждение если папку создать не удалось
if err := os.Mkdir(resultsDir, 0777); err != nil {
// likely dir is already exists
}

Убрать зависимость от go-openapi

Как я понимаю go-openapi используется только в checker_scheme, который вообще по-умолчанию в библиотеке не используется. Однако эта зависимость есть в go.mod и go.sum.

Может убрать из последних файлов зависимость от go-openapi? Большинству пользователей библиотеки, как я понимаю это не нужно, а дефолтная зависимость тем не менее присутствует, что добавляет в проект не только зависимость от go-openapi, но и от пачки других библиотек.

Нужна поддержка работы с AeroSpike

Для тестирования интеграции с AeroSpike необходимы:

  • механизм загрузки фикстур
  • checker записей

Думаю, фикстуры имеет смысл сделать по аналогии с обычной БД
В качестве асерта мне нравится подход в моках: мы можем запрашивать данные по структуре namespace->set->key. И делать несколько таких проверок в рамках теста.

Gonkey не дожидается обращений в моки после получения response

Столкнулись с такой ситуацией что сервис не всегда может дожидаться результатов запросов в свои зависимости.
Как следствие проверка мока calls = возвращает ошибку.

Проблему можно решить явным ожиданием после request добавив еще одну паузу.
Также можно добавить в мок timeout + ожидание заданного количества calls, что более предпочтительно.

Возможность параметризации заголовов

Привет!

Есть ли в gonkey возможность параметризации заголовка?

Кейс следующий - необходимо протестить различные состояния бекенда в зависимости от определенного заголовка(айдишник пользователя).

Я сначала написал скрипт вида:

  Content-Type: application/json
  X-UserId:  {{ .userID }}

и потом радостный пошел расписывать секцию cases, но понял, что для headers отсутствует такая секция для cases.

Посоветуйте пожалуйста, как лучше решить проблему параметризации заголовков.

Автогенерация данных в запросах и ответах моков

Разработать и реализовать нотации по аналогии с переменными, по которым будут возможность автоматически сгенерировать значение по выбранному шаблону и далее использовать его для запроса или ответа мока.
Предположительно это должен быть набор шаблонов, соответствующий набору методов выбранной библиотеке faker.

Например если у https://github.com/brianvoe/gofakeit есть метод Number(min int, max int)
То мы можем добавить для него нотацию вида

    {
      "jsonrpc": "2.0",
      "id": "{{ $fakeNumber(1,10) }}",
     }

Заменить имя suite с Gonkey на путь до папки с тестами которая передается в Runner

В #85 речь идет о консольном отчете и там удобнее видеть путь до конкретного файла с тетсами.

Я допускаю, что имена тестов могут совпадать глобально, но в рамках одного suite такого быть не должно.
Кроме того совпадение имен порождает другую проблему.

Gonkey мапит список результатов на структуру отчета для AllureReport и в этом xml ключом будет имя теста.
Мы теряем часть отчетов.

Чтобы такого не было нужно либо задавать уникальные имена, либо переписывать allure adapter.

Я попробовал на своем проекте добавить прозрачности передавая в suite name путь который получает Runner.
Trim, конечно, придется убрать для универсальности.

Screenshot 2021-05-17 at 14 14 01

Как результат, отчеты стали вот такие

Screenshot 2021-05-17 at 14 05 01

Screenshot 2021-05-17 at 13 45 28

AsyncAwait в моках и DB

Уже обсуждалось в #41
Хотим все же попробовать проработать вариант с асинхронными версиями проверок в базе и входящих колов в моки, чтобы все было честно.

По сути такое есть asserts Gomega https://onsi.github.io/gomega/#making-asynchronous-assertions и хочется такого же в Gonkey :)

Позже опишем свое предложение подробнее

Переменные в описании теста

Очень нехватает возможности использования переменных в файле описания теста.

Например:

- name: "my_request"
  # ...
  request: "tag={{test_tag}}"

Для чего это требуется:

  • Выносить из тестов в env-файл приватную информацию; Например: jwt, параметры доступа и т.п.)
  • Выносить в общую переменную дублирующуюся информацию; Например: часто встречающиеся значения параметров (tag=test и т.п.)
  • Возможность использования результатов предыдущего запроса; Например: можно будет запрос '/get_last_post_id', получив в ответе ID поста, протестировать следующий: '/get_post_info?id={{last_post_id}}'

Отдельно про env-файлы:
Это очень удобно для переключения контекста тестирования: мы можем тестировать API на продакшене, на стэйдже / тестовых серверах, на локальном сервере. Для всех этих случаев часто хочется иметь набор разных значений параметров для запросов.

В целом, все вышеописанное я не выдумал, а встречал в проектах, в чем-то аналогичных Gonkey. К примеру, у JetBrains есть нечто подобное: https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html#using_request_vars
Если не ошибаюсь, у Postman тоже.

Я понимаю, что задача не самая простая, и я готов взяться за её реализацию. Если даёте зеленый свет, я сначала согласую с вами пимерный план действий (как именно вышеописанное будет реализовано), что бы не было разнагласий по коду, и лишь потом приступлю к работе.
Данный функционал мне очень нужен в текущих проектах, поэтому работа не затянется до бесконечности и не будет заброшена.

Возможно также, что все это уже есть в том или ином виде, и я просто проглядел. Если так, прошу подсказать мне, в какую сторону смотреть.

Collision in field and table name causes issues

Faced an error function row_to_json(integer) does not exist on loading fixture to the table, one column of which named the same as the table.

Happens because under the hood Gonkey constructs following query:

INSERT INTO "level" ("brand_id", "cashback_factor", "level") VALUES (6577, 0.05, 2) RETURNING row_to_json("level")

Possible solution is to stop using RETURNING row_to_json() in favour of RETURNING * and to scan result into the struct (adopt one of existing libraries for this job).

Assert responses with additional rules

Hi,

I would like to test the following scenario.

- name: "Test"
  method: POST
  path: /jsonrpc/v1/update
  request: |
    {
      "jsonrpc": "2.0",
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "method": "update",
      "params": {
        "id": "{{ $event_ref }}",
        "field1": "123",
        "field1": "456"
      }
    }

Under some condition based on field1 and field2 values a system under test should generate a new ID which is not equal to request.id variable.

At the moment I can assert that response id matches some pattern but cannot verify that it is different from $event_ref value

  response:
    200: |
      {
         "jsonrpc":"2.0",
         "id":"550e8400-e29b-41d4-a716-446655440000",
         "result":{
            "id":"$matchRegexp(\\b[0-9a-f]{8}\\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\\b[0-9a-f]{12}\\b)",
             "field1": "123",
             "field1": "456"
         }
      }

Please consider adding such functionality.
Thank you

Писать пути до файлов в результатах тестов

Сейчас там есть только имя теста, а имена в разных файлах могут пересекаться. Очень неудобно.

Пример типичного вывода после запуска теста:

Name: my_good_test

Request:
     Method: GET
       Path: /some_path
      Query: ?params=values
       Body:
<no body>

Response:
     Status: 200 OK
       Body:
{"status":"ERROR"}

     Result: ERRORS!

Errors:

1) at path $.status values do not match:
     expected: OK
       actual: ERROR



..............
..................................................
Failed tests: 1/10

Process finished with exit code 1

Если у нас несколько тестов с именем my_good_test в разных файлах, то невозможно понять, какой из них сфэйлился.

Добавить возможность очищать таблицы перед выполнением каждого теста

В настоящий момент мы никак не можем задать пустую таблицу (очистить отдельную таблицу/всю базу или задать пустую таблицу через фикстуру).

Есть три варианта как это можно было бы сделать:

  1. всегда чистить все таблицы базы вперед прогоном тестов внутри одного yaml файла
  • очистка таблиц будет только в рамках одного yaml
  • все под капотом
  1. добавить параметр в runner и опираясь на него чистить все таблицы базы перед каждым исполнением теста
  • придется запускать в отдельном ране флоу тесты
  • еще один параметр в раннере
  1. добавить нотацию фикстур возможность обозначать таблицы которые должны быть пустыми
  • все под капотом
  • очистка задается явным образом

Для начала хотелось бы обсудить, какой из вариантов наиболее подходящий

Добавить логирование и вывод результатов исполнения before/after scripts

Расширить models.Result, чтобы он также содержал скрипты(before/after) и результаты их исполнения.
Соответственно расширить вывод результатов в консоль и allure report.
В случае ошибки исполнения before-скрипта останавливать выполнение теста.
Также нужно переработать cmd_helper чтобы он выводил в консоль лог выполнения скрипта.

Новая проверка expectedQuery описана в readme некорректо(ru, eng)

В readme в примере допущена ошибка
Example:

  ...
  mocks:
    service1:
      requestConstraints:
        # this check will demand that the request contains key1 и key2
        # and the values are key1=value1, key1=value11 и key2=value2. 
        # Keys not mentioned here are omitted while running the check.
        - kind: expectedQuery
          query:  key1=value1&key2=value2&key1=value11
    ...

На самом деле в шаблоне используются другие ключи

     requestConstraints:
       - kind: queryMatches
         expectedQuery: key1=value1&key2=value2&key1=value11

Если передать db, но не передать DbType, тест паникует

В документации нигде параметр не описан + паника не самый лучший вариант выхода
Предлагаю:

  1. Добавить в документацию DbType, раз он обязательный, если передаем db.
  2. Изменить сигнатуру ответа fixtures.NewLoader - возвращать ошибку а-ля
    func NewLoader(cfg *Config) (Loader, error) {}. Соответственно выше можно ошибку поймать и вызвать например t.Fatal(err)
    Также можно добавить метод к структуре fixtures.Config метод func (config Config) validate() error {} который будет возвращать ошибку, если DB == nil или DbType неизвестный.

Проверка даты по шаблону

Добавить нотацию, которая позволит использовать паттерны вида $matchDate(format, formula) и будет поддерживать:

  • динамические данные вида текущие дата-время-часовой пояс с точностью до минуты/секунды и т.д
  • поддержка различных форматов времени через указания шаблона
  • возможность использовать конструкции вида (NOW - 1 day) через указание формулы

Для записи $matchDate(yyyy-mm-dd, now - 1 day) фактическое время будет округлено с точностью до дня и будет вычтен 1 день.

Нотацию предполагается применять как при формировании запросов так и в проверках(response, mock request, db response)

Passing variables to DB query

I would like to see the functionality of passing variables in dbQueryArgs, dbResponseArgs, dbQuery and dbResponse. For example:

response:
    200: |
      {
        "jsonrpc":"2.0",
        "id":"550e8400-e29b-41d4-a716-446655440000",
        "result":{
          "id": "$matchRegexp(\\b[0-9a-f]{8}\\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\\b[0-9a-f]{12}\\b)",
        }
      }
  variables_to_set:
    200:
      ref: "result.id"

  dbQuery: |
    SELECT a, b, c
    FROM t1
    WHERE ref = '{{ .ref }}'

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.