TL; DR: контролируйте последовательность тестирования. Поскольку это интеграционные тесты, это не большое «нет-нет», если бы они были модульными тестами.
Я обнаружил, что, используя переменную stati c для записи правил, которые оцениваются как истинные, и обеспечивая последний тест have-all-rules-as-true , согласно совету здесь https://hamidmosalla.com/2018/08/16/xunit-control-the-test-execution-order/, становится тривиально легко достичь того, что мне нужно.
В случае, если ссылка умирает, вот как реализовать этот подход
Сначала создайте AlphabeticalOrderer
, реализующий xUnit ITestCaseOrderer
:
public class AlphabeticalOrderer : ITestCaseOrderer
{
public IEnumerable<TTestCase> OrderTestCases<TTestCase>(IEnumerable<TTestCase> testCases)
where TTestCase : ITestCase
{
var result = testCases.ToList();
result.Sort((x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.TestMethod.Method.Name, y.TestMethod.Method.Name));
return result;
}
}
Затем используйте вновь созданный атрибут на свой тестовый класс и создайте переменную stati c для записи прогресса:
[TestCaseOrderer("MyCompany.AlphabeticalOrderer", "MyTestsDLL")]
public class RulesTests
{
private static List<Rule> _untestedRules;
public RulesTests()
{
if (_untestedRules == null) // this will run once per [Fact]
{
_untestedRules = <some way of getting all the rules> // this will only run first time around
}
}
Каждый раз, когда срабатывает правило, запишите, какое это было правило:
private void MarkRuleAsTested(LendingRule testedRule)
{
var rulesToRemove = _untestedRules.Where(r => r.Logic == testedRule.Logic).ToList();
foreach (var ruleToRemove in rulesToRemove)
{
_untestedRules.Remove(ruleToRemove);
}
}
Затем последний тест для запуска следует проверить коллекцию:
[Fact]
public void ZZ_check_all_rules_have_been_triggered_by_other_tests()
{
// This test must run last because it validates that the
// OTHER tests taken together have resulted in each rule
// being evaluated as true at least once.
if (!_untestedRules.Any())
{
return;
}
var separator = "\r\n------------------------\r\n";
var untestedRules = string.Join(separator, _untestedRules.Select(ur => $"Logic: {ur.Logic}"));
throw new SomeRulesUntestedException($"The following rules have not been tested to resolve as True: {separator}{untestedRules}{separator}");
}
Это приводит к хорошо читаемой ошибке теста.
Вы также можете начать с пустой коллекции c _testedRules
и конец сравните этот набор с полным набором правил.