Behaveでテストを繰り返し実施していると、
失敗したシナリオだけを再実行したい時があります。

そのような場合、
次のリンク先にあるように、テスト結果のフォーマットを「rerun」にすると、
失敗したシナリオのみ再実行することができます。

features/formatter.rerun.feature | behave/behave | GitHub https://github.com/behave/behave/blob/main/features/formatter.rerun.feature

このエントリでは、
Allure Behave(allure_behave.formatter:AllureFormatter)を使って、
同様のことができるように考えていきます。

allure-behaveのセットアップ

Pythonの仮想環境を作成、allure-behaveをセットアップします。

python -m venv venv
. venv/bin/activate
pip install behave
pip install allure-behave

テストコード・設定の準備

テストコードと設定を準備します。レポートはAllure形式で出力させます。

sample.feature

Feature: sample feature

  Scenario: senario1
    When process1

  Scenario: senario2
    When process2

steps/sample.py

import sys
from behave import *

@when("process1")
def step_impl(context):
  assert True

@when("process2")
def step_impl(context):
  assert False

.behaverc

[behave]
format=allure_behave.formatter:AllureFormatter
outfiles=allure-results

テスト結果フォーマット「rerun」を使って再実行する方法

まずは、テスト結果のフォーマットを「rerun」にして再実行する方法です。

以下のようにオプション-f,-oを付けてbehaveを実行します。

$ behave -f rerun -o failed_scenarios.txt

Failing scenarios:
  sample.feature:6  senario2

0 features passed, 1 failed, 0 skipped
1 scenario passed, 1 failed, 0 skipped
1 step passed, 1 failed, 0 skipped, 0 undefined
Took 0m0.000s

失敗したシナリオが出力ファイルに記録されます。

$ cat failed_scenarios.txt
# -- RERUN: 1 failing scenarios during last test run.
sample.feature:6

出力ファイルを指定してbehaveを実行すると、
失敗したシナリオのみ実行(成功済みシナリオはスキップ)されます。

$ behave @failed_scenarios.txt
Feature: sample feature # sample.feature:1

  Scenario: senario1  # sample.feature:3
    When process1     # None

  Scenario: senario2  # sample.feature:6
    When process2     # steps/sample.py:8 0.001s

※途中省略※

Failing scenarios:
  sample.feature:6  senario2

0 features passed, 1 failed, 0 skipped
0 scenarios passed, 1 failed, 1 skipped
0 steps passed, 1 failed, 1 skipped, 0 undefined
Took 0m0.001s

allureの結果から未実施・失敗したテストを再実行する方法

次に、allureの結果から未実施・失敗したテストを再実行する方法です。

ちなみに、rerunとallureの結果を両方出力したいだけであれば、
-f,-oのオプションを2つ付けてbehaveを実行するだけでよいです。
ここでは、allureの結果に含まれているテスト結果から、
最後に実行したテストでパスしたもの以外を再実行することを考えます。
(featureファイルを指定して部分的に実行した結果をまとめるケースを考慮します)

テストケース・テスト結果から再実行の対象をリストする、
次のようなスクリプトを作成します。

build_failure_scenarios.py

import os
import glob
import json
import behave.parser
import behave.model
import behave.model_core

# load features
scenarios = {}
features_dir = os.path.join(os.path.dirname(__file__))
for f in glob.glob(os.path.join(features_dir, "*.feature")):
    for e in behave.parser.parse_file(f).scenarios:
        scenarios[(e.feature.name, e.name)] = e.location

# load results
test_results_latest = {}
result_dir = os.path.join(os.path.dirname(__file__), "allure-results")
for s in sorted(glob.glob(os.path.join(result_dir, "*.json")), key=os.path.getmtime):
    with open(s) as fp:
        obj = json.loads(fp.read())
    label_map = {e["name"]:e["value"] for e in obj.get("labels", [])}
    if obj.get("status") != "skipped":
      test_results_latest[(label_map.get("feature"), obj.get("name"))] = obj.get("status")
test_results_passed = {k for k,v in test_results_latest.items() if v == "passed"}

# write rerun scenarios
rerun_targets = [f'./{v.basename()}:{v.line}' for k,v in scenarios.items() if k not in test_results_passed]
with open(os.path.join(features_dir, "rerun_scenarios.txt"), "w") as fp:
    fp.write("\n".join(rerun_targets))
    fp.write("\n")

スクリプトを実行します。

$ python build_failure_scenarios.py

失敗したシナリオが出力ファイルに記録されます。

$ cat rerun_scenarios.txt
./sample.feature:6

出力ファイルの結果にしたがって、テストを再実行します。

$ behave @rerun_scenarios.txt
Feature: sample feature # sample.feature:1

  Scenario: senario1  # sample.feature:3
    When process1     # None

  Scenario: senario2  # sample.feature:6
    When process2     # steps/sample.py:8 0.000s

※途中省略※

Failing scenarios:
  sample.feature:6  senario2

0 features passed, 1 failed, 0 skipped
0 scenarios passed, 1 failed, 1 skipped
0 steps passed, 1 failed, 1 skipped, 0 undefined
Took 0m0.000s

以上。