SpecFlow рдЖрдкрдХреЛ рдбреЗрдЯрд╛ рд╕рдВрдЪрд╛рд▓рд┐рдд рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдореНрдмреЗрдбреЗрдб рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЕрдкрдиреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рдореБрдЭреЗ рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде рджреЛ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛:
- рдХрднреА-рдХрднреА, рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рдЖрдк рдПрдХ рдкрд░реАрдХреНрд╖рдг рд╕реЗ рдСрдЯреЛ-рдкреНрд░рд▓реЗрдЦрди рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдкреАрдЖрдИ рдкрд░реАрдХреНрд╖рдг)
- рдЬрдм рдбреЗрдЯрд╛ рдХреА рдорд╛рддреНрд░рд╛ рдмрдбрд╝реА рд╣реЛрддреА рд╣реИ, рддреЛ рдЗрд╕реЗ рдЕрд▓рдЧ рд╕реЗ рд╕реНрдЯреЛрд░ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реЛрддрд╛ рд╣реИ (рдЕрдХреНрд╕рд░ рдПрдХреНрд╕реЗрд▓ рдПрдХреНрд╕реЗрдкреНрдЯреЗрдВрд╕ рдЯреЗрд╕реНрдЯ рдХреЗрд╕реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ)
Gesigner рдЬрдирд░реЗрдЯ рдХреЛрдб рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЕрдлрд╡рд╛рд╣, рдореИрдВ рджреЛрдиреЛрдВ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛ред
рдЖрдЗрдП рдЙрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрдзрд╛рд░ рд╡рд░реНрдЧ рд▓рд┐рдЦреЗрдВ рдЬреЛ рдбреАрдПрд╕рдПрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ
[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); } }
рдПрдХ рдШреЛрд╖рдгрд╛рддреНрдордХ рд╢реИрд▓реА рдореЗрдВ рдлрд╝реАрдЪрд░ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЕрдкрдиреА рд╡рд┐рд╢реЗрд╖рддрд╛ рд▓рд┐рдЦрддреЗ рд╣реИрдВред рд╣рдо NUnit рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдлрд╝реАрдЪрд░ рдХреЗ рд▓рд┐рдП рд░рд┐рдкреЛрд░реНрдЯ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╡рд┐рд╡рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдЗрд╕рдореЗрдВ рд╕реЗ рдЕрдкрдиреА рд╡рд┐рд╢реЗрд╖рддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗред
[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> </specFlow>
рдпрд╣реА рд╕рдм рд╣реИ, рдЕрдм SpecFlow.exe рдХреЗ рд╕рд╛рде рдЖрдк рдПрдХ рд╕реБрдВрджрд░ рд░рд┐рдкреЛрд░реНрдЯ рддреИрдпрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ

рдЗрд╕ рддрд░рд╣ рдЖрдк рдмрд╣реБрдд рд╕рд╛рд░реЗ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдПрдкреАрдЖрдИ рдФрд░ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд▓рд┐рдП рдСрдЯреЛ-рдкреНрд░рд▓реЗрдЦрди рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред