SpecFlow позволяет использовать встроенные таблицы для Data Driven сценариев. В своей практике я столкнулся с двумя проблемами при таком подходе:
- Иногда хочется, наоборот, получить авто-документацию из теста (тестирование API)
- Когда количество данных велико, лучше хранить их где-то отдельно
Покопавшись в Gesigner Generated коде я смог решить обе проблемы.
Напишем базовый класс для тестов, которые не будут использовать DSL
[TestFixture] public class DslGenerationTestsBase : TestsBase { private static ITestRunner _testRunner; [TestFixtureSetUp] public virtual void FeatureSetup() { _testRunner = TestRunnerManager.GetTestRunner(); var features = GetType().GetCustomAttributes(typeof (FeatureAttribute), false); if (!features.Any()) { throw new ConfigurationErrorsException("Feature Attribute is required"); } var feature = (FeatureAttribute)features.Single(); var featureInfo = new FeatureInfo( new System.Globalization.CultureInfo("en-US"), feature.Title, feature.Story, ProgrammingLanguage.CSharp, null); _testRunner.OnFeatureStart(featureInfo); } [TestFixtureTearDown] public virtual void FeatureTearDown() { _testRunner.OnFeatureEnd(); _testRunner = null; } [TearDown] public virtual void TearDown() { _testRunner.OnScenarioEnd(); } protected void ScenarioSetup(ScenarioInfo scenarioInfo) { _testRunner.OnScenarioStart(scenarioInfo); } protected void ScenarioCleanup() { _testRunner.CollectScenarioErrors(); } protected void Given(string given, string keyword = "Given ") { _testRunner.Given(given, null, null, keyword); } protected void When(string when, string keyword = "When ") { _testRunner.When(when, null, null, keyword); } protected void Then(string then, string keyword = "Then ") { _testRunner.Then(then, null, null, keyword); } }
Для того, чтобы описать Feature в декларативном стиле, напишем собственный атрибут. Мы используем NUnit. Для того, чтобы Feature попала в отчет необходимо использовать DescriptionAttribute. Поэтому, унаследуем наш атрибут от него.
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class FeatureAttribute : DescriptionAttribute { public string Title { get; private set; } public string Story { get; private set; } public CultureInfo CultureInfo { get; private set; } public FeatureAttribute(string title, string story):base(title) { Title = title; Story = story; CultureInfo = new CultureInfo("en-US"); } public FeatureAttribute(string title, string story, CultureInfo cultureInfo) : base(title) { Title = title; Story = story; CultureInfo = cultureInfo; } }
И напишем класс с тестом
Вместо TestCase можно использовать TestCaseSource и читать данные из любого формата.
[Binding] [Feature("DslGeneration", "In order to avoid silly mistakes\n" + "As a math idiot\n" + "I want to be told the sum of two numbers")] [Category("Examples")] public class DataDrivenDslGenerationExample : DslGenerationTestsBase { private decimal _a; private decimal _b; [TestCase("1", "2", "3")] [TestCase("2", "3", "5")] public void CodeSomeTest_DslIsGenerated(string a, string b, string c) { var scenarioInfo = new ScenarioInfo("DslGeneration Outline", null); ScenarioSetup(scenarioInfo); Given("Calculator is on"); When(string.Format("User fill {0} and {1}", a, b)); Then(string.Format("{0} is returned", c)); ScenarioCleanup(); } [Given(@"Calculator is on")] public void CalculatorIsOn() { } [When(@"User fill (.*) and (.*)")] public void Fill(int a, int b) { _a = a; _b = b; } [Then(@"(.*) is returned")] public void ResultReturned(int c) { var actual = _a + _b; Assert.AreEqual(c, actual); } }
Если ваш базовый класс находится в другой сборке, то нужно будет добавить ее в конфигурацию:
<specFlow> <stepAssemblies> <stepAssembly assembly="..." /> </stepAssemblies> <!-- For additional details on SpecFlow configuration options see http://go.specflow.org/doc-config --> </specFlow>
Вот и все, теперь с помощью SpecFlow.exe можно сгенерировать красивый отчет
Таким образом, можно создать авто-документацию для API и сценариев с большим количеством данных.
ссылка на оригинал статьи http://habrahabr.ru/post/181311/
Добавить комментарий