Data Driven Tests & SpecFlow

от автора

SpecFlow позволяет использовать встроенные таблицы для Data Driven сценариев. В своей практике я столкнулся с двумя проблемами при таком подходе:

  1. Иногда хочется, наоборот, получить авто-документацию из теста (тестирование API)
  2. Когда количество данных велико, лучше хранить их где-то отдельно

Покопавшись в 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *