savetest-cli 0.1.2__tar.gz → 0.3.0rc1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- savetest_cli-0.3.0rc1/PKG-INFO +423 -0
- savetest_cli-0.3.0rc1/README.md +413 -0
- {savetest_cli-0.1.2 → savetest_cli-0.3.0rc1}/pyproject.toml +2 -2
- savetest_cli-0.3.0rc1/savetest_cli/__init__.py +1 -0
- savetest_cli-0.3.0rc1/savetest_cli/cli.py +1411 -0
- savetest_cli-0.3.0rc1/savetest_cli.egg-info/PKG-INFO +423 -0
- savetest_cli-0.1.2/PKG-INFO +0 -188
- savetest_cli-0.1.2/README.md +0 -178
- savetest_cli-0.1.2/savetest_cli/__init__.py +0 -1
- savetest_cli-0.1.2/savetest_cli/cli.py +0 -376
- savetest_cli-0.1.2/savetest_cli.egg-info/PKG-INFO +0 -188
- {savetest_cli-0.1.2 → savetest_cli-0.3.0rc1}/MANIFEST.in +0 -0
- {savetest_cli-0.1.2 → savetest_cli-0.3.0rc1}/savetest_cli/pwa-512x512.png +0 -0
- {savetest_cli-0.1.2 → savetest_cli-0.3.0rc1}/savetest_cli.egg-info/SOURCES.txt +0 -0
- {savetest_cli-0.1.2 → savetest_cli-0.3.0rc1}/savetest_cli.egg-info/dependency_links.txt +0 -0
- {savetest_cli-0.1.2 → savetest_cli-0.3.0rc1}/savetest_cli.egg-info/entry_points.txt +0 -0
- {savetest_cli-0.1.2 → savetest_cli-0.3.0rc1}/savetest_cli.egg-info/requires.txt +0 -0
- {savetest_cli-0.1.2 → savetest_cli-0.3.0rc1}/savetest_cli.egg-info/top_level.txt +0 -0
- {savetest_cli-0.1.2 → savetest_cli-0.3.0rc1}/setup.cfg +0 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: savetest-cli
|
|
3
|
+
Version: 0.3.0rc1
|
|
4
|
+
Summary: CLI for SaveTest: upload Allure results as a ZIP, as raw files, or by watching a directory
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.8
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: click>=8.0
|
|
9
|
+
Requires-Dist: requests>=2.28
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<img src="savetest_cli/pwa-512x512.png" alt="SaveTest" width="128">
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
# savetest-cli
|
|
16
|
+
|
|
17
|
+
CLI-утилита для загрузки Allure-результатов в SaveTest. Старые команды `zip_report` и `upload` упаковывают и грузят ZIP. `upload_results` и `upload_files` отправляют сырые файлы `allure-results` без архива. `watch` следит за каталогом и отправляет файлы по мере появления.
|
|
18
|
+
|
|
19
|
+
## Установка
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install savetest-cli
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Быстрый старт
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# 1. Упаковать директорию с результатами в ZIP
|
|
31
|
+
savetest zip_report ./AllureReport
|
|
32
|
+
|
|
33
|
+
# 2. Загрузить в SaveTest и дождаться создания тест-рана
|
|
34
|
+
export SAVETEST_HOST=https://savetest.example.com
|
|
35
|
+
export SAVETEST_TOKEN=sat_xxxxxxxxxxxxxxxx
|
|
36
|
+
export SAVETEST_PROJECT_ID=42
|
|
37
|
+
export SAVETEST_BRANCH=main
|
|
38
|
+
|
|
39
|
+
savetest upload --test-run-name "Smoke $(date +%Y-%m-%d)"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Переменные окружения
|
|
45
|
+
|
|
46
|
+
Все параметры можно задать через переменные окружения — не нужно указывать флаги при каждом вызове.
|
|
47
|
+
|
|
48
|
+
| Переменная | Обязательна | Описание |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `SAVETEST_HOST` | да | URL вашего SaveTest, например `https://savetest.example.com` |
|
|
51
|
+
| `SAVETEST_TOKEN` | да | API-токен (создаётся в настройках профиля SaveTest) |
|
|
52
|
+
| `SAVETEST_PROJECT_ID` | да | ID проекта в SaveTest |
|
|
53
|
+
| `SAVETEST_BRANCH` | нет | Ветка Git, привязываемая к тест-рану |
|
|
54
|
+
| `SAVETEST_TEST_RUN_ID` | нет | ID существующего тест-рана (если не задан — создаётся новый) |
|
|
55
|
+
| `SAVETEST_TEST_RUN_NAME` | нет | Имя нового тест-рана |
|
|
56
|
+
| `SAVETEST_TEST_RUN_DESCRIPTION` | нет | Описание нового тест-рана |
|
|
57
|
+
| `SAVETEST_TEST_RUN_VERSION` | нет | Версия системы |
|
|
58
|
+
| `SAVETEST_TEST_RUN_REVISION` | нет | Ревизия / номер сборки |
|
|
59
|
+
| `SAVETEST_TEST_RUN_OBJECT` | нет | Объект тестирования |
|
|
60
|
+
| `SAVETEST_EPIC_ID` | нет | ID эпика для привязки тест-рана |
|
|
61
|
+
| `SAVETEST_EPIC_NAME` | нет | Наименование эпика в проекте (если ID неизвестен) |
|
|
62
|
+
| `SAVETEST_CONFIGURATION_ID` | нет | ID конфигурации тест-рана |
|
|
63
|
+
| `SAVETEST_CONFIGURATION_NAME` | нет | Наименование конфигурации в проекте |
|
|
64
|
+
| `SAVETEST_INCLUDE_ATTACHMENTS` | нет | `true` — включать вложения в ZIP, `false` — исключать (быстрее) |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Команды
|
|
69
|
+
|
|
70
|
+
### `savetest zip_report <path>`
|
|
71
|
+
|
|
72
|
+
Упаковывает директорию с Allure-результатами в ZIP-архив.
|
|
73
|
+
|
|
74
|
+
По умолчанию вложения (картинки, видео, `*-attachment.json`) **не включаются** — архив получается меньше и грузится быстрее. Флаг `--include-attachments` включает их.
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
savetest zip_report [OPTIONS] PATH
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
| Опция | По умолчанию | Описание |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| `PATH` | — | Путь к директории с Allure-результатами |
|
|
83
|
+
| `--output`, `-o` | `allure-results.zip` | Путь к выходному ZIP-файлу |
|
|
84
|
+
| `--include-attachments` | выключено | Включить вложения (картинки, видео, `*-attachment.json`) |
|
|
85
|
+
|
|
86
|
+
**Примеры:**
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
savetest zip_report ./AllureReport
|
|
90
|
+
|
|
91
|
+
savetest zip_report ./AllureReport --output report.zip
|
|
92
|
+
|
|
93
|
+
savetest zip_report ./AllureReport --include-attachments
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### `savetest upload`
|
|
99
|
+
|
|
100
|
+
Загружает ZIP-файл в SaveTest по частям и ждёт завершения импорта. По завершении выводит ссылку на созданный тест-ран.
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
savetest upload [OPTIONS]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
| Опция | Env-переменная | По умолчанию | Описание |
|
|
107
|
+
|---|---|---|---|
|
|
108
|
+
| `--host` | `SAVETEST_HOST` | — | URL SaveTest (**обязательно**) |
|
|
109
|
+
| `--token`, `-t` | `SAVETEST_TOKEN` | — | API-токен (**обязательно**) |
|
|
110
|
+
| `--project-id`, `-p` | `SAVETEST_PROJECT_ID` | — | ID проекта (**обязательно**) |
|
|
111
|
+
| `--zip-file`, `-z` | — | `allure-results.zip` | Путь к ZIP-файлу |
|
|
112
|
+
| `--branch`, `-b` | `SAVETEST_BRANCH` | — | Ветка Git |
|
|
113
|
+
| `--test-run-name` | `SAVETEST_TEST_RUN_NAME` | — | Имя нового тест-рана |
|
|
114
|
+
| `--description` | `SAVETEST_TEST_RUN_DESCRIPTION` | — | Описание нового тест-рана |
|
|
115
|
+
| `--version` | `SAVETEST_TEST_RUN_VERSION` | — | Версия системы |
|
|
116
|
+
| `--revision` | `SAVETEST_TEST_RUN_REVISION` | — | Ревизия / номер сборки |
|
|
117
|
+
| `--test-object` | `SAVETEST_TEST_RUN_OBJECT` | — | Объект тестирования |
|
|
118
|
+
| `--epic-id` | `SAVETEST_EPIC_ID` | — | ID эпика |
|
|
119
|
+
| `--epic-name` | `SAVETEST_EPIC_NAME` | — | Наименование эпика в проекте |
|
|
120
|
+
| `--configuration-id` | `SAVETEST_CONFIGURATION_ID` | — | ID конфигурации |
|
|
121
|
+
| `--configuration-name` | `SAVETEST_CONFIGURATION_NAME` | — | Наименование конфигурации |
|
|
122
|
+
| `--test-run-id` | `SAVETEST_TEST_RUN_ID` | — | ID существующего тест-рана |
|
|
123
|
+
| `--include-attachments` | `SAVETEST_INCLUDE_ATTACHMENTS` | выключено | Сообщить серверу, что ZIP содержит вложения |
|
|
124
|
+
| `--chunk-size` | — | `50` | Размер чанка при загрузке (МБ) |
|
|
125
|
+
| `--wait` / `--no-wait` | — | `--wait` | Ждать завершения импорта |
|
|
126
|
+
| `--timeout` | — | `3600` | Таймаут ожидания (сек) |
|
|
127
|
+
| `--poll-interval` | — | `1.5` | Интервал опроса статуса (сек) |
|
|
128
|
+
|
|
129
|
+
`--host`, `--token` и `--project-id` обязательны. Передавайте их через флаги или переменные окружения.
|
|
130
|
+
|
|
131
|
+
**Примеры:**
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Через переменные окружения (рекомендуется)
|
|
135
|
+
export SAVETEST_HOST=https://savetest.example.com
|
|
136
|
+
export SAVETEST_TOKEN=sat_xxxxxxxxxxxxxxxx
|
|
137
|
+
export SAVETEST_PROJECT_ID=42
|
|
138
|
+
|
|
139
|
+
savetest upload --branch main --test-run-name "Regression $(date +%Y-%m-%d)"
|
|
140
|
+
|
|
141
|
+
# Новый тест-ран с эпиком, конфигурацией и метаданными
|
|
142
|
+
savetest upload \
|
|
143
|
+
--branch main \
|
|
144
|
+
--test-run-name "Smoke $(date +%Y-%m-%d)" \
|
|
145
|
+
--epic-name "Release 2.4" \
|
|
146
|
+
--configuration-name "Chrome / Windows" \
|
|
147
|
+
--version "2.4.0" \
|
|
148
|
+
--description "Nightly smoke on staging"
|
|
149
|
+
|
|
150
|
+
# Загрузить в существующий тест-ран
|
|
151
|
+
savetest upload --branch main --test-run-id 17
|
|
152
|
+
|
|
153
|
+
# Загрузить другой ZIP с вложениями, не ждать импорта
|
|
154
|
+
savetest upload --zip-file full-report.zip --include-attachments --no-wait
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### `savetest upload_results <path>`
|
|
160
|
+
|
|
161
|
+
Загружает каталог сырых результатов (`allure-results`, до `allure generate`) файлами, без ZIP. Файлы уходят пачками в ту же очередь, что и архив. Вложения по умолчанию не отправляются.
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
savetest upload_results [OPTIONS] PATH
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Флаги подключения, тест-рана, `--wait` и `--timeout` те же, что у `upload`. Нет `--zip-file` и `--chunk-size`.
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
savetest upload_results ./allure-results \
|
|
171
|
+
--test-run-name "Nightly $(date +%Y-%m-%d)" \
|
|
172
|
+
--revision "$CI_COMMIT_SHORT_SHA"
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
### `savetest upload_files <file...>`
|
|
178
|
+
|
|
179
|
+
Загружает один файл или явно перечисленные файлы. Каталог целиком передавайте в `upload_results`. ZIP эта команда не принимает.
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
savetest upload_files ./allure-results/*-result.json ./allure-results/executor.json
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
### `savetest watch <path>`
|
|
188
|
+
|
|
189
|
+
Висит и смотрит каталог. Файл готов, когда размер не меняется `--settle` секунд и JSON читается. Готовые файлы не уходят по одному: если они появляются подряд, watch копит их `--batch-window` секунд после последнего нового и отправляет пачкой. Дольше `--batch-max-wait` секунд пачка не держится. Одна отправка — не больше 20 файлов или 32 МБ. Каталога может ещё не быть: команда дождётся его появления.
|
|
190
|
+
|
|
191
|
+
Остановка:
|
|
192
|
+
|
|
193
|
+
- Ctrl+C или `SIGTERM` — забирает уже готовые файлы и выходит;
|
|
194
|
+
- `--timeout СЕКУНД` — то же по таймеру, `0` (по умолчанию) значит «пока не остановят»;
|
|
195
|
+
- `--idle-timeout СЕКУНД` — выйти, когда каталог затих. `0` выключает этот режим.
|
|
196
|
+
|
|
197
|
+
Первая пачка создаёт тест-ран, если не передан `--test-run-id`. Следующие файлы пишутся в тот же ран: пока ран не создан, вторая пачка ждёт. Код возврата `1`, если хотя бы один импорт не завершился как `completed`.
|
|
198
|
+
|
|
199
|
+
Вложение уезжает вместе с `*-result.json`, который на него ссылается. Результат подождёт вложение до `--attachment-wait` секунд. Пачка без файла результата не отправляется.
|
|
200
|
+
|
|
201
|
+
Привязки к фреймворку нет. После `--` watch запускает любую команду как есть и не разбирает её аргументы: pytest, JUnit, Maven, Gradle, npm или свой скрипт. Ему всё равно, кто пишет файлы. Нужны только `*-result.json` в каталоге, который указан первым аргументом. `pytest` в примерах ниже — один из вариантов, не требование.
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
savetest watch ./allure-results \
|
|
205
|
+
--include-attachments \
|
|
206
|
+
--test-run-name "Локальный прогон" \
|
|
207
|
+
--timeout 0
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Запуск в CI
|
|
213
|
+
|
|
214
|
+
Команды `zip_report` и `upload` остаются для уже настроенных пайплайнов. Для нового пайплайна берите `upload_results`: архив на раннере не нужен, сервер не собирает ZIP из чанков, а код возврата `1` при `failed` и `partial` роняет джобу.
|
|
215
|
+
|
|
216
|
+
Правила:
|
|
217
|
+
|
|
218
|
+
- Токен — маскируемая переменная `SAVETEST_TOKEN`, не пароль пользователя и не лог.
|
|
219
|
+
- Загрузку ставьте после тестов с `when: always` / `if: always()`, иначе упавший прогон не попадёт в SaveTest.
|
|
220
|
+
- Если тесты и загрузка — разные джобы, отдайте каталог `allure-results` артефактом тоже с `when: always`.
|
|
221
|
+
- `--wait` оставляйте включённым: джоба должна завершиться только когда импорт дошёл до конца.
|
|
222
|
+
- Вложения включайте только если они реально нужны. По умолчанию CLI их не шлёт.
|
|
223
|
+
- `0.3.0rc1` — предварительная версия для SaveTest 1.5.0: `pip install savetest-cli==0.3.0rc1`. Обычный `pip install savetest-cli` остаётся на последней стабильной версии.
|
|
224
|
+
|
|
225
|
+
### Результаты по мере прогона
|
|
226
|
+
|
|
227
|
+
`upload_results` показывает ран только после тестов. Чтобы кейсы появлялись во время прогона, запускайте тесты из `watch`, как это делает Allure TestOps: `allurectl watch -- ./gradlew test`. Команда пишется после `--`. Это не команда pytest: на её месте может быть любой фреймворк и любой запускаемый файл. `watch` остаётся на переднем плане, сам ждёт эту команду и выходит вместе с ней. Сборка не остаётся с фоновым процессом.
|
|
228
|
+
|
|
229
|
+
`--idle-timeout` для CI не нужен: пауза между тестами похожа на конец прогона. Код возврата — код тестов, а если тесты зелёные и импорт упал, то `1`.
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
mkdir -p allure-results
|
|
233
|
+
savetest watch allure-results \
|
|
234
|
+
--test-run-name "CI ${CI_PIPELINE_ID}" \
|
|
235
|
+
--revision "${CI_COMMIT_SHORT_SHA}" \
|
|
236
|
+
-- pytest --alluredir=allure-results
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### GitLab CI
|
|
240
|
+
|
|
241
|
+
```yaml
|
|
242
|
+
test:
|
|
243
|
+
stage: test
|
|
244
|
+
image: python:3.11-slim
|
|
245
|
+
variables:
|
|
246
|
+
SAVETEST_HOST: https://savetest.example.com
|
|
247
|
+
SAVETEST_PROJECT_ID: "42"
|
|
248
|
+
SAVETEST_BRANCH: $CI_COMMIT_REF_NAME
|
|
249
|
+
script:
|
|
250
|
+
- pip install --quiet pytest allure-pytest savetest-cli
|
|
251
|
+
- mkdir -p allure-results
|
|
252
|
+
- savetest watch allure-results
|
|
253
|
+
--test-run-name "GitLab ${CI_PROJECT_NAME} #${CI_PIPELINE_ID}"
|
|
254
|
+
--revision "${CI_COMMIT_SHORT_SHA}"
|
|
255
|
+
-- pytest --alluredir=allure-results
|
|
256
|
+
artifacts:
|
|
257
|
+
when: always
|
|
258
|
+
expire_in: 1 day
|
|
259
|
+
paths:
|
|
260
|
+
- allure-results/
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
`SAVETEST_TOKEN` — Masked variable. Артефакт оставлен как запасная копия: в SaveTest результаты уже ушли во время тестов.
|
|
264
|
+
|
|
265
|
+
#### GitHub Actions
|
|
266
|
+
|
|
267
|
+
```yaml
|
|
268
|
+
- name: Watch and test
|
|
269
|
+
env:
|
|
270
|
+
SAVETEST_HOST: ${{ vars.SAVETEST_HOST }}
|
|
271
|
+
SAVETEST_TOKEN: ${{ secrets.SAVETEST_TOKEN }}
|
|
272
|
+
SAVETEST_PROJECT_ID: ${{ vars.SAVETEST_PROJECT_ID }}
|
|
273
|
+
SAVETEST_BRANCH: ${{ github.ref_name }}
|
|
274
|
+
run: |
|
|
275
|
+
pip install pytest allure-pytest savetest-cli
|
|
276
|
+
mkdir -p allure-results
|
|
277
|
+
savetest watch allure-results \
|
|
278
|
+
--test-run-name "GitHub ${{ github.workflow }} #${{ github.run_number }}" \
|
|
279
|
+
--revision "${{ github.sha }}" \
|
|
280
|
+
-- pytest --alluredir=allure-results
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### GitLab CI
|
|
284
|
+
|
|
285
|
+
```yaml
|
|
286
|
+
test:
|
|
287
|
+
stage: test
|
|
288
|
+
script:
|
|
289
|
+
- pytest --alluredir=allure-results
|
|
290
|
+
artifacts:
|
|
291
|
+
when: always
|
|
292
|
+
expire_in: 1 day
|
|
293
|
+
paths:
|
|
294
|
+
- allure-results/
|
|
295
|
+
|
|
296
|
+
upload_savetest:
|
|
297
|
+
stage: report
|
|
298
|
+
when: always
|
|
299
|
+
image: python:3.11-slim
|
|
300
|
+
needs: ["test"]
|
|
301
|
+
variables:
|
|
302
|
+
SAVETEST_HOST: https://savetest.example.com
|
|
303
|
+
SAVETEST_PROJECT_ID: "42"
|
|
304
|
+
SAVETEST_BRANCH: $CI_COMMIT_REF_NAME
|
|
305
|
+
script:
|
|
306
|
+
- pip install --quiet savetest-cli
|
|
307
|
+
- savetest upload_results allure-results
|
|
308
|
+
--test-run-name "GitLab ${CI_PROJECT_NAME} #${CI_PIPELINE_ID}"
|
|
309
|
+
--revision "${CI_COMMIT_SHORT_SHA}"
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
`SAVETEST_TOKEN` задайте в **Settings → CI/CD → Variables** с флагами Masked и Protected. Это вариант «загрузить всё после тестов», без слежения.
|
|
313
|
+
|
|
314
|
+
Если тесты и загрузка в одной джобе, артефакт не нужен: вызывайте `upload_results` в `after_script`.
|
|
315
|
+
|
|
316
|
+
### GitHub Actions
|
|
317
|
+
|
|
318
|
+
```yaml
|
|
319
|
+
- name: Tests
|
|
320
|
+
if: always()
|
|
321
|
+
run: pytest --alluredir=allure-results
|
|
322
|
+
|
|
323
|
+
- name: Upload Allure results
|
|
324
|
+
if: always()
|
|
325
|
+
env:
|
|
326
|
+
SAVETEST_HOST: ${{ vars.SAVETEST_HOST }}
|
|
327
|
+
SAVETEST_TOKEN: ${{ secrets.SAVETEST_TOKEN }}
|
|
328
|
+
SAVETEST_PROJECT_ID: ${{ vars.SAVETEST_PROJECT_ID }}
|
|
329
|
+
SAVETEST_BRANCH: ${{ github.ref_name }}
|
|
330
|
+
run: |
|
|
331
|
+
pip install savetest-cli
|
|
332
|
+
savetest upload_results allure-results \
|
|
333
|
+
--test-run-name "GitHub ${{ github.workflow }} #${{ github.run_number }}" \
|
|
334
|
+
--revision "${{ github.sha }}"
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Настройка в Jenkins
|
|
340
|
+
|
|
341
|
+
Этот пример оставлен для ZIP-команд `zip_report` и `upload`. Чтобы не собирать архив, замените две команды на одну: `savetest upload_results "${WORKSPACE}/allure-results"`.
|
|
342
|
+
|
|
343
|
+
Добавьте токен в **Jenkins → Manage Jenkins → Credentials** (тип: Secret text, ID: `savetest-token`).
|
|
344
|
+
|
|
345
|
+
В `Jenkinsfile` используйте `withCredentials` и `parameters`, чтобы не хранить конфигурацию в коде:
|
|
346
|
+
|
|
347
|
+
```groovy
|
|
348
|
+
pipeline {
|
|
349
|
+
agent any
|
|
350
|
+
|
|
351
|
+
parameters {
|
|
352
|
+
string(name: 'SAVETEST_HOST', defaultValue: '', description: 'URL SaveTest')
|
|
353
|
+
string(name: 'SAVETEST_PROJECT_ID', defaultValue: '', description: 'ID проекта в SaveTest')
|
|
354
|
+
string(name: 'SAVETEST_BRANCH', defaultValue: '', description: 'Ветка Git')
|
|
355
|
+
string(name: 'SAVETEST_TEST_RUN_ID',defaultValue: '', description: 'ID тест-рана (пусто = создать новый)')
|
|
356
|
+
booleanParam(name: 'INCLUDE_ATTACHMENTS', defaultValue: false, description: 'Включать вложения в ZIP')
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
stages {
|
|
360
|
+
// ... ваши стадии запуска тестов ...
|
|
361
|
+
|
|
362
|
+
stage('Upload to SaveTest') {
|
|
363
|
+
steps {
|
|
364
|
+
withCredentials([string(credentialsId: 'savetest-token', variable: 'SAVETEST_TOKEN')]) {
|
|
365
|
+
sh '''
|
|
366
|
+
pip install savetest-cli
|
|
367
|
+
|
|
368
|
+
savetest zip_report "${WORKSPACE}/AllureReport" \
|
|
369
|
+
$([ "${INCLUDE_ATTACHMENTS}" = "true" ] && echo "--include-attachments")
|
|
370
|
+
|
|
371
|
+
savetest upload \
|
|
372
|
+
--host "${SAVETEST_HOST}" \
|
|
373
|
+
--project-id "${SAVETEST_PROJECT_ID}" \
|
|
374
|
+
--branch "${SAVETEST_BRANCH}" \
|
|
375
|
+
--test-run-name "Jenkins ${JOB_NAME} #${BUILD_NUMBER}" \
|
|
376
|
+
$( [ -n "${SAVETEST_TEST_RUN_ID}" ] && echo "--test-run-id ${SAVETEST_TEST_RUN_ID}" ) \
|
|
377
|
+
$( [ "${INCLUDE_ATTACHMENTS}" = "true" ] && echo "--include-attachments" )
|
|
378
|
+
'''
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
> `SAVETEST_TOKEN` берётся из Jenkins Credentials и передаётся в окружение через `withCredentials` — в лог и в код сборки он не попадает.
|
|
387
|
+
|
|
388
|
+
### Результаты по мере прогона
|
|
389
|
+
|
|
390
|
+
В Jenkins `watch` на переднем плане без команды тестов шаг не отпустит: команда специально не завершается. Вариант `watch &` тоже опасен. Jenkins связан с шагом трубами stdout и stderr и ждёт их закрытия. Фоновый процесс наследует эти трубы, шаг может не закончиться, даже когда оболочка уже вышла. Это описано в [Spawning Processes From Build](https://www.jenkins.io/doc/book/managing/spawning-processes/).
|
|
391
|
+
|
|
392
|
+
Allure TestOps так не запускает слежение. В CI это `allurectl watch -- ./gradlew clean test`: агент остаётся главным процессом, сам стартует тесты и выходит, когда они закончились. Плагин Jenkins делает то же обёрткой `withAllureUpload { sh './gradlew clean test' }`.
|
|
393
|
+
|
|
394
|
+
Здесь тот же приём. После `--` — любая команда, не только pytest: `mvn test`, `./gradlew clean test`, `npm test` или свой скрипт. Watch к фреймворку не привязан. Пока команда идёт, шаг занят ею. Когда она выходит, watch дописывает готовую пачку и завершает шаг. Отдельный `kill` не нужен. Лимит времени ставьте на стадию Jenkins, не через `--timeout`: ноль у `--timeout` здесь значит «пока не кончится команда после `--`». В примере ниже стоит pytest только как иллюстрация.
|
|
395
|
+
|
|
396
|
+
```groovy
|
|
397
|
+
stage('Test') {
|
|
398
|
+
steps {
|
|
399
|
+
withCredentials([string(credentialsId: 'savetest-token', variable: 'SAVETEST_TOKEN')]) {
|
|
400
|
+
sh '''
|
|
401
|
+
pip install savetest-cli pytest allure-pytest
|
|
402
|
+
mkdir -p allure-results
|
|
403
|
+
savetest watch allure-results \
|
|
404
|
+
--host "${SAVETEST_HOST}" \
|
|
405
|
+
--project-id "${SAVETEST_PROJECT_ID}" \
|
|
406
|
+
--branch "${SAVETEST_BRANCH}" \
|
|
407
|
+
--test-run-name "Jenkins ${JOB_NAME} #${BUILD_NUMBER}" \
|
|
408
|
+
--revision "${BUILD_NUMBER}" \
|
|
409
|
+
-- pytest --alluredir=allure-results
|
|
410
|
+
'''
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## Получение API-токена
|
|
419
|
+
|
|
420
|
+
1. Войдите в SaveTest.
|
|
421
|
+
2. Откройте **Настройки профиля → API-токены**.
|
|
422
|
+
3. Создайте новый токен и скопируйте его значение.
|
|
423
|
+
4. Добавьте токен в Jenkins Credentials (или экспортируйте локально через `export SAVETEST_TOKEN=...`).
|