Я только что столкнулся с BBD и specflow, и это выглядит очень интересным. При записи пользовательских историй они обычно находятся на высоком уровне и пользователях агента GUI. Таким образом, при записи сценариев они обычно будут тестом GUI или интеграционным тестом от высокого уровня системы. Но что относительно модульного теста далее вниз в решении? Например, сервисные конечные точки, бизнес-объекты, и т.д. я должен записать новые сценарии для тех или являюсь там способом снова использовать те же сценарии для низкоуровневого тестирования (модульные тесты), или я должен скопировать и мимо сценариев?
Сообщите мне, есть ли у меня все это неправильно.
Фреймворки BDD, такие как SpecFlow, предназначены для помощи членам технической команды в общении легче с нетехническими заинтересованными сторонами проекта.
Спецификации на английском языке нелегко поддерживать или реорганизовывать. Поскольку единственные люди, которые читают тесты или примеры на уровне модулей, являются техническими специалистами и могут читать код, я предпочитаю использовать на этом уровне фреймворки для модульного тестирования, такие как NUnit.
Сценарии часто намного сложнее, чем модульные тесты. Обычно я нахожу, что они охватывают ряд комбинаций внутренней бизнес-логики, и за каждый аспект, составляющий комбинацию, будет отвечать отдельная единица кода.Следовательно, логика в сценариях будет разделена между несколькими различными модульными тестами, и вы не сможете их скопировать.
Иногда я использую сценарии для проведения модульных тестов. Я мог бы обнаружить, что часть логики в конечном итоге является ответственностью конкретной единицы кода, и тогда я могу скопировать только соответствующие шаги из сценария в модульные тесты в качестве комментария.
// Given I have $100 in my account
var account = new Mock<Account>();
account.SetupGet(a => a.Balance).Returns(100);
var accountProvider = new Mock<AccountProvider>();
accountProvider.Setup(ap => ap.AccountFor("lunivore")).Returns(account);
// When I ask for $20
var atm = new ATM(accountProvider);
atm.PutInCardFor("lunivore");
int money = atm.RequestMoney(20);
// Then I should get $20
Assert.AreEqual(20, money);
// And my account should have paid out $20
account.verify(a => a.PayOut(20));
Я рекомендую вам скопировать язык, на котором написаны сценарии (например: PayOut
). Это согласуется с «вездесущим языком» доменного дизайна. Внедрение этого языка как в модульные тесты, так и в код также помогает команде общаться с заинтересованными сторонами, потому что вам не придется делать перевод снова и снова.
Добавление в комментарии Given / When / Then также действительно помогает мне сосредоточиться на доставке кода, который действительно будет использоваться, вместо того, чтобы пытаться угадать все крайние случаи. Код наилучшего качества - это то, что вы не пишете.
Удачи!