Как вызвать сценарий несколько раз без табличных элементов в тесте поведения?
Я хотел бы назвать сценарий - скажем, 500 раз - в тесте на огурец без табличных элементов. Причина в том, что я хотел бы использовать рандомизированные переменные вместо того, чтобы писать сам. Я знаю, как реализовать произвольную функциональность в тестах, но она вызывается только один раз.
Например:
Scenario Outline: I want to test speed with different values
When I set the speed to <speed>
And I wait for 5 seconds
Then it plays at <speed>
Examples:
| speed |
| 10 |
| 20 |
| 30 |
| 40 |
| 50 |
импортировать случайный
скорости = ['10', '20', '30', '40', '50']
def next_speed (): вернуть random.choice(скорость)
Если я использую такую случайную функцию, как я могу вызвать этот сценарий 500 раз?
Заранее спасибо.
3 ответа
from __future__ import print_function
import functools
from behave.model import ScenarioOutline
def patch_scenario_with_autoretry(scenario, max_attempts=3):
"""Monkey-patches :func:`~behave.model.Scenario.run()` to auto-retry a
scenario that fails. The scenario is retried a number of times
before its failure is accepted.
This is helpful when the test infrastructure (server/network environment)
is unreliable (which should be a rare case).
:param scenario: Scenario or ScenarioOutline to patch.
:param max_attempts: How many times the scenario can be run.
"""
def scenario_run_with_retries(scenario_run, *args, **kwargs):
for attempt in range(1, max_attempts+1):
if not scenario_run(*args, **kwargs):
if attempt > 1:
message = u"AUTO-RETRY SCENARIO PASSED (after {0} attempts)"
print(message.format(attempt))
return False # -- NOT-FAILED = PASSED
# -- SCENARIO FAILED:
if attempt < max_attempts:
print(u"AUTO-RETRY SCENARIO (attempt {0})".format(attempt))
message = u"AUTO-RETRY SCENARIO FAILED (after {0} attempts)"
print(message.format(max_attempts))
return True
if isinstance(scenario, ScenarioOutline):
scenario_outline = scenario
for scenario in scenario_outline.scenarios:
scenario_run = scenario.run
scenario.run = functools.partial(scenario_run_with_retries, scenario_run)
else:
scenario_run = scenario.run
scenario.run = functools.partial(scenario_run_with_retries, scenario_run)
Ссылка: https://github.com/behave/behave/blob/master/behave/contrib/scenario_autoretry.py
Я думал об этом время от времени последние пару лет, пока использовал Behave. Я использую его для управления функциональной тестовой средой для критически важных радиостанций, а также среды, в которой они находятся (воспроизведение / запись звука, глубокое изучение файлов WAV для подтверждения содержимого, работа с их пользовательским интерфейсом и навигация для создания сообщений, вроде того).
Раньше мне приходилось пытаться зацикливать вещи за пределами одной строки с предоставленной таблицей данных.
Пока я исследовал некоторые углубления объекта Content, я углубился в интерпретатор, и мне интересно, смогу ли я заставить его реализовать что-то вроде этого:
When I loop i 5 times
And I perform this action
And I perform another action
Then I should see this result
And loop back to i
Это не нарушит синтаксис корнишона, и если я могу реализовать что-то в шагах цикла, которые каким-то образом перемотают синтаксический анализатор, он должен запустить их снова. Я подозреваю, что самая сложная часть - обеспечить сохранение результатов всех шагов: мне нужно было бы вникнуть в структуры, используемые для хранения результатов, чтобы выходные данные отображали все итерации.
Кто-нибудь еще пытался реализовать это в Behave с помощью определенных шагов?
Если вы попытаетесь использовать корнишон в качестве инструмента для написания сценариев, у вас будет плохое время. Для этого есть гораздо лучшие инструменты, такие как сам Python или фреймворк робота. Спросите себя, какое преимущество вы ожидаете от теста на корнишоны. Ваш корнишон должен ответить "почему", вы делаете что-то, у него должны быть примеры, которые объясняют достаточно разные случаи - и, желательно, только интересные.
Вам нужно добавлять динамические строки каждый раз для теста. Он никогда не будет отображаться в файле объектов, но ему нужно добавить строки.
Следующие ссылки имеют несколько функций, которые будут создавать динамические строки для вас в определении шага
http://www.programcreek.com/java-api-examples/index.php?api=gherkin.formatter.model.DataTableRow
или вызов определения шага из определения шага
http://www.specflow.org/documentation/Calling-Steps-from-Step-Definitions/
Надеюсь, я понимаю ваш вопрос:)
Как насчет этого:
Измените шаг: "Когда я установлю скорость на скорость" на
Когда я устанавливаю скорость {скорость}, чтобы он принял аргумент.
В вашей функции: Когда я проверяю скорость 500 раз И на этом этапе: Когда я проверяю скорость 500 раз, вы:
==> создать цикл for 500 раз:
=====> выберите случайную скорость
=====> выполнить другие шаги с context.execute_steps и форматировать (скорость)
Вам придется немного обойти это, потому что для этого нужны юникоды, а не целые числа.
==> Тем не менее, можно согласиться с Сабо Питером, что немного неловко использовать для этого gherkin / python-ведут себя:). Это как-то портит цель. Кроме того, даже в соответствии с моим мышлением здесь, это может быть сделано более элегантно.
Вы можете найти некоторые хорошие вещи здесь: https://jenisys.github.io/behave.example/tutorials/tutorial08.html Cheerz
Так что редактируйте после комментария: (после редактирования и написания этого примера это выглядит еще более глупо, чем я думал, так что да: не используйте для этого поведения. Пример:
Функция: функция тестирования. Сценарий: сценарий тестирования. Я открываю приложение, когда тестирую приложение 500 раз на произвольной скорости, после чего консоль говорит, что все готово.
шаги:
@given (ты открываешь приложение)
=> def I_open_the_app (context):
==> # код для открытия приложения
@when(я тестирую приложение 500 раз на произвольной скорости)
=> def I_test_the_app_500_times_at_random_speed (context):
==> для времен в диапазоне (1500):
===> random_speed = random.randint (min_speed, max_speed)
===> context.execute_steps (u '' ', когда я играю в {speed}' ''. format (speed = str (random_speed))
@when(ты играешь на {скорости} ')
=> def I_play_at (контекст, скорость)
==> play_at_speed (интермедиат (скорость))
@then (консоль говорит, что все готово)
=> def the_console_says_it_is_done ==> print ('готово')