lamoda / gonkey Goto Github PK
View Code? Open in Web Editor NEWGonkey - a testing automation tool
License: MIT License
Gonkey - a testing automation tool
License: MIT License
Уже обсуждалось в #41
Хотим все же попробовать проработать вариант с асинхронными версиями проверок в базе и входящих колов в моки, чтобы все было честно.
По сути такое есть asserts Gomega https://onsi.github.io/gomega/#making-asynchronous-assertions и хочется такого же в Gonkey :)
Позже опишем свое предложение подробнее
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!
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.
Расширить models.Result, чтобы он также содержал скрипты(before/after) и результаты их исполнения.
Соответственно расширить вывод результатов в консоль и allure report.
В случае ошибки исполнения before-скрипта останавливать выполнение теста.
Также нужно переработать cmd_helper чтобы он выводил в консоль лог выполнения скрипта.
Добавить нотацию, которая позволит использовать паттерны вида $matchDate(format, formula) и будет поддерживать:
Для записи $matchDate(yyyy-mm-dd, now - 1 day) фактическое время будет округлено с точностью до дня и будет вычтен 1 день.
Нотацию предполагается применять как при формировании запросов так и в проверках(response, mock request, db response)
How to reproduce:
...
mocks:
someservice:
strategy: uriVary
uris:
v1/test:
calls: 1
strategy: file
filename: responses/test.json
...
mock someservice: at path $.uriVary.v1/test: number of calls does not match: expected 1, actual 0
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?
Один из наших тестов фейлится из-за того, что сравнение с 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()
}
}
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?
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.
Чтобы не ломать обратную совместимость можно добавить новые нотации, либо все же переработать старые.
Эта фича имеет смысл после реализации #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
In case of using "https://github.com/fescobar/allure-docker-service" which uses standard allure report generator all gonkey dates become invalid (dates are in the far future), each timestamp should be additionally divided to 1000 (it will be 1000 000 in total) to obtain correct date and time in ui.
При прогонке тестов возник 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
}
Если написать в схеме вот так
response:
200: |
{
"result": {
"data": {
"id": "$matchRegexp(^[0-9]+$)"
}
}
}
то будет ошибка, что тип не совпадает. Наверное нужно сделать проверку на тип необязательной, если сравниваем по регулярному выражению
В случае если это будет мок предлагается использовать 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 позволяющий проверить наличие данных.
Как я понимаю go-openapi используется только в checker_scheme, который вообще по-умолчанию в библиотеке не используется. Однако эта зависимость есть в go.mod и go.sum.
Может убрать из последних файлов зависимость от go-openapi? Большинству пользователей библиотеки, как я понимаю это не нужно, а дефолтная зависимость тем не менее присутствует, что добавляет в проект не только зависимость от go-openapi, но и от пачки других библиотек.
Принцип тот же что и с запросами/моками в #138
Сейчас Gonkey умеет проверять массивы только на точное соответствие, т.е. набор элементов строго фиксирован. Но некоторых случаях мы не можем точно знать это количество, либо оно очень большое.
Нужно подумать и добавить возможность проверять общий случай.
Пример ответа сервера:
{
"status": "OK",
"url": ["https://some-url-1.com", "https://some-url-2.com"]
}
Проблемы:
Список может быть большим, и нет смысла описывать его целиком в кейсе.
Решение: проверять элементы по общему паттерну (regexp) и/или проверять их количество
Порядок элементов может быть не детерминирован. К примеру, в кейсе список описан так: ["value_1", "value_2"], и если от сервера придет ["value_2", "value_1"], тест сфэйлится.
Решение: добавить возможность проверки наличия всех элементов, не зависимости от порядка.
Крмое того, могут оказаться полезными проверки included / not included, что бы проверять, что в списке есть или отсутствует конкретные элемент.
Добавить в ответ мока поддержку нотации вида {{ $request.field1.field2 }}, которая позволит подставить в ответ значение полученное из пришедшего запроса.
Пример:
strategy: constant
body: >
{
"order_nr": "{{ $request.otder_nr }}",
}
В 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
Реализовать интерфейс через который можно будет передавать/получать/проверять логи приложения в Gonkey.
Логи как и моки должны очищаться в конце теста.
Реализовать logger checker, который будет проверять содержимое и тип сообщения в логах (необходимо проработать стратегии проверки).
Реализовать нотации для yaml-тетсов.
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 }}'
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_request"
# ...
request: "tag={{test_tag}}"
Для чего это требуется:
Отдельно про env-файлы:
Это очень удобно для переключения контекста тестирования: мы можем тестировать API на продакшене, на стэйдже / тестовых серверах, на локальном сервере. Для всех этих случаев часто хочется иметь набор разных значений параметров для запросов.
В целом, все вышеописанное я не выдумал, а встречал в проектах, в чем-то аналогичных Gonkey. К примеру, у JetBrains есть нечто подобное: https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html#using_request_vars
Если не ошибаюсь, у Postman тоже.
Я понимаю, что задача не самая простая, и я готов взяться за её реализацию. Если даёте зеленый свет, я сначала согласую с вами пимерный план действий (как именно вышеописанное будет реализовано), что бы не было разнагласий по коду, и лишь потом приступлю к работе.
Данный функционал мне очень нужен в текущих проектах, поэтому работа не затянется до бесконечности и не будет заброшена.
Возможно также, что все это уже есть в том или ином виде, и я просто проглядел. Если так, прошу подсказать мне, в какую сторону смотреть.
При выполнении запроса в БД 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.
Добавить возможность проверки отдельных значений в dbResponse по регулярке.
Например, чтобы была возможна такая конструкция:
dbResponse:
- '{
"city": "Новгород",
"revision_id": "$matchRegexp(^[0-9a-fA-F]{8}$)"
}'
- '{
"city": "Москва",
"revision_id": "$matchRegexp(^[0-9a-fA-F]{8}$)"
}'
Как оказалось requestConstraints.bodyMatchesXML не позволяет проверять вложенный объект и не поддерживает regexp. Таким образом не получается избежать непредсказуемых данных.
Решение:
В requestConstraints.bodyMatchesJSON уже есть поддержка regexp.
Необходимо добавить ее и в стратегию bodyMatchesXML.
Если в энвах нет GONKEY_ALLURE_DIR то отчет не создается. Необходимо сообщать об этом при старте теста.
gonkey/runner/runner_testing.go
Lines 83 to 87 in ccdae22
gonkey/output/allure_report/allure_report.go
Lines 23 to 25 in ccdae22
How I can send file(s) with json fields by POST? (Как отправить файл вместе с json полями POST-ом)
В #85 речь идет о консольном отчете и там удобнее видеть путь до конкретного файла с тетсами.
Я допускаю, что имена тестов могут совпадать глобально, но в рамках одного suite такого быть не должно.
Кроме того совпадение имен порождает другую проблему.
Gonkey мапит список результатов на структуру отчета для AllureReport и в этом xml ключом будет имя теста.
Мы теряем часть отчетов.
Чтобы такого не было нужно либо задавать уникальные имена, либо переписывать allure adapter.
Я попробовал на своем проекте добавить прозрачности передавая в suite name путь который получает Runner.
Trim, конечно, придется убрать для универсальности.
Как результат, отчеты стали вот такие
Сейчас там есть только имя теста, а имена в разных файлах могут пересекаться. Очень неудобно.
Пример типичного вывода после запуска теста:
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 в разных файлах, то невозможно понять, какой из них сфэйлился.
В настоящий момент мы никак не можем задать пустую таблицу (очистить отдельную таблицу/всю базу или задать пустую таблицу через фикстуру).
Есть три варианта как это можно было бы сделать:
Для начала хотелось бы обсудить, какой из вариантов наиболее подходящий
Проблема: при использовании стратегии sequence, если запросы во внешнюю систему выполняются параллельно невозможно предсказать какой ответ должен вернуть мок. Стратегия позволяет лишь обозначить порядок ответов.
Решение: добавить в стратегию sequence флаг basedOnRequest, по которому мок будет давать ответ только если успешно пройден requestConstraints. В таком случае каждый степ становится уникальным и при получении запроса мок проверяет его по всем requestConstraints. Ответ берется из первого пройденного.
Алтернатива с названием: оформить как отдельную стратегию basedOnRequest
Столкнулись с такой ситуацией что сервис не всегда может дожидаться результатов запросов в свои зависимости.
Как следствие проверка мока calls = возвращает ошибку.
Проблему можно решить явным ожиданием после request добавив еще одну паузу.
Также можно добавить в мок timeout + ожидание заданного количества calls, что более предпочтительно.
Разработать и реализовать нотации по аналогии с переменными, по которым будут возможность автоматически сгенерировать значение по выбранному шаблону и далее использовать его для запроса или ответа мока.
Предположительно это должен быть набор шаблонов, соответствующий набору методов выбранной библиотеке faker.
Например если у https://github.com/brianvoe/gofakeit есть метод Number(min int, max int)
То мы можем добавить для него нотацию вида
{
"jsonrpc": "2.0",
"id": "{{ $fakeNumber(1,10) }}",
}
Для тестирования интеграции с AeroSpike необходимы:
Думаю, фикстуры имеет смысл сделать по аналогии с обычной БД
В качестве асерта мне нравится подход в моках: мы можем запрашивать данные по структуре namespace->set->key. И делать несколько таких проверок в рамках теста.
В документации нигде параметр не описан + паника не самый лучший вариант выхода
Предлагаю:
DbType
, раз он обязательный, если передаем db
.fixtures.NewLoader
- возвращать ошибку а-ляfunc NewLoader(cfg *Config) (Loader, error) {}
. Соответственно выше можно ошибку поймать и вызвать например t.Fatal(err)
fixtures.Config
метод func (config Config) validate() error {}
который будет возвращать ошибку, если DB == nil
или DbType
неизвестный.Также как мы проверяем значения полей в jsonBody будет удобно проверять и отдельные значения в query.
Например, чтобы была возможна такая конструкция ?jsonrpc=2.0&order_nr=$matchRegexp(^[0-9]{9}$)
Я бы хотел добавить afterScript по аналогии с beforeScript для того, что бы обновить materialised views перед dbQuery. На данный момент обновить их можно использовать beforeScript и dbQuery во втором тесте, но это костыль и делает тесты менее очевидными.
Необходима функциональность как в wiremock - https://wiremock.org/docs/simulating-faults/
У нас уже есть возможность указывать Status и Body.
Необходимо добавить стратегии вида:
Нужно больше контроля над запуском тестов.
Возможность запускать отдельный файл хорошо, но куда удобней иметь переключатель в самом тесте.
Предлагаю также помечать тесты которые мы хотим пропустить этими же статусами и не выполнять их.
Так мы сможем
Мы пробрасывает результат в поле status в AllureReport и там уже предполагается набор состояний
Привет!
Есть ли в gonkey возможность параметризации заголовка?
Кейс следующий - необходимо протестить различные состояния бекенда в зависимости от определенного заголовка(айдишник пользователя).
Я сначала написал скрипт вида:
Content-Type: application/json
X-UserId: {{ .userID }}
и потом радостный пошел расписывать секцию cases, но понял, что для headers отсутствует такая секция для cases.
Посоветуйте пожалуйста, как лучше решить проблему параметризации заголовков.
Добавить в стратегию file возможность перезаписывать отдельные поля json-файла.
Предположительное решение - расширить нотацию file полем overrideParams
Пример:
strategy: file
filename: mocks_data/some.json
overrideParams:
order[0].amount: 1000.01
In case destination service hosted using https endpoint it is impossible to use gonkey command line, because gonkey console uses hard coded http schema.
При попытке собрать под 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
Можно ли организовать эти изменения в инструменте?
Go 1.13 is already out for a few month. It's time to update :)
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).
Line 54 in 3b352f9
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.