Friday, June 24, 2011

Detailed Description

Prerequisites:
- VS2010 Premium, No Resharper

- SpecFlow
1.6.1
- MSTests
provided by VS2010
- Coded UI Test – provided by VS 2010
References:
Behavior Driven Development vs. Test Driven
Development:
http://xkormachev-bddvstdd.blogspot.com

 Solution Layout










 




#1. Coded UI Test project
#2. Application under
development/testing, projected as Windows
Forms Application, contains View, and probably Model parts, to be
tested with Coded UI Test and common Unit Test (MSTests)
during Behavior Driven Development. Unit Tests might be used to test
Model.

#3. Special class MsTest2010CodedUiGeneratorProvider used to provide
Coded UI invocation from SpecFlow test. It
is referenced in App.config (#5) as
<unitTestProvider name="MsTest" generatorProvider="SpecflowCodedUIGenerator.MsTest2010CodedUiGeneratorProvider,
...
#4. SpecFlow
test, projected as Coded UI Test to be able
to access running application on Coded UI Test steps. It is implemented
as a separated test project to run separately with Ctrl + F5, it is set as StartUp Project at final stage of this example. (N.B.: Unit Test projects doesn’t provide proper access to running application.)

#5. Contains description enabling to run SpecFlow
with Coded UI Test.

Example:

1. File -> New -> Project… (Windows
Forms Application), name SfAndCuiCalculator


2. Create Simple Calculator Form













3. Test it: Ctrl+F5. Enter 4 into textBox1, enter 3 into textBox2.
Press Add button


4. Into solution SfAndCuiCalculator: Test
-> New Test … (Coded UITest), name CuiCalculateAddition.cs,
project name CodedUITest, next you see the
dialog, press OK














5. Record Coded UI
Test: Run SfAndCuiCalculator application (press Ctrl + F5). Start Recorder, Enter 4 to the first textBox, Enter 3 to the second text Box, press Add. Stop Recorder.





 

 

6. Press Show Recorder Steps:








Press Add and Generate button.

Exit Recorder.

Check Coded UI Test.
Close
 running application window. Click Test-> Run -> Tests in Current Context


7. Inside the solution create a new test project: Test -> New Test…
(Coded UI Test), name CodedUITest1.cs. Check the field: Add to Test Project: Create a new Visual C# project …, project name SpecFlowTest. This step is
needed to be able to run Coded UI test inside the SpecFlow test. If you choose Unit Test project for SpecFlow, you would not be able to get access to the running application under test, so you would not be able to run Coded UI test.





8. For next dialog choose “Cancel”






9. In project SpecFlowTest, delete file CodedUITest.cs
10. Create a folder AcceptanceTests
inside SpecFlowTest







11. For AcceptanceTests folder (right click): Add -> New Item:






Change Name: CalculateAddition.feature, put there the following Gherkin stuff:
Feature: Addition
    This is a simple test to demonstrate
    SpecFlow
and CodedUI testing

    SpecFlow
should used to support AcceptanceTests and Model testing

   And CodedUI is used to test UI

@mytag

Scenario
: Add two numbers
Given
I have got the right sum of 3 and 4

When
I press add

Then
the result should be 7 on the screen and in the model field

12. Create a folder StepDefinitions inside SpecFlowTest

13. For StepDefinition folder (right click): Add -> New Item:










Change Name: CalculateAddition.cs
14. Add Reference to SpecFlowTest : TeckTalk.SpecFlow

15. Clean StepDefinition -> CalculateAddition.cs to look as:
. . .
namespace
SpecFlow.StepDefinitions
 {

    [Binding]
 public class CalculateAddition
    {


     }

}


16. To be able to run Coded UI tes from SpecFlow, it is necessary to have additional class. So right click the solution -> Add -> New Project… (Class Library), name SpecflowCodedUIGenerator, rename Class1.cs to
MsTest2010CodedUiGeneratorProvider.cs, put there the following:

//see: https://github.com/techtalk/SpecFlow/wiki/Using-SpecFlow-with-CodedUI-API
using System.CodeDom;
using
TechTalk.SpecFlow.Generator.UnitTestProvider;
namespace
SpecflowCodedUIGenerator
 {

    public
class MsTest2010CodedUiGeneratorProvider : MsTest2010GeneratorProvider
   {

      public
override void SetTestFixture(System.CodeDom.CodeTypeDeclaration typeDeclaration,
                                                                 string
title, string description)
     {

         base
.SetTestFixture
(typeDeclaration, title, description);
         foreach
(CodeAttributeDeclaration customAttribute in typeDeclaration.CustomAttributes)
        {

            if
(customAttribute.Name == "Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute")
            {

               typeDeclaration.CustomAttributes.Remove
(customAttribute);

               break
;

            }
      }


      typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference("Microsoft.VisualStudio.TestTools.UITesting.CodedUITestAttribute")));
    }

 }

}

Add TechTalk.SpecFlow.Generator as a Reference to
the SpecflowCodedUIGenerator project.

17. Build SpecflowCodedUIGenerator. Then
put its dll to SpecFlow deployment location. E.g.

copy From C:\al\dev\SpecFlow\SfAndCuiCalculator\SpecflowCodedUIGenerator\bin\Debug\SpecflowCodedUIGenerator.dll
To
C:\Program Files\TechTalk\SpecFlow
Restart VS2010
!

18. Add App.config to SpecFlowTest

<?xml version="1.0" encoding="utf-8" ?>
<
configuration>
    <
configSections>
    <
section name="specFlow" type="TechTalk.SpecFlow.Configuration.ConfigurationSectionHandler, TechTalk.SpecFlow"/>
    </
configSections>
    <
specFlow>
    <
unitTestProvider name="MsTest" generatorProvider="SpecflowCodedUIGenerator.MsTest2010CodedUiGeneratorProvider
SpecflowCodedUIGenerator" runtimeProvider="TechTalk.SpecFlow.UnitTestProvider.MsTest2010RuntimeProvider,TechTalk.SpecFlow"/>
     </
specFlow>
</
configuration>

 19. To rebuild effectively you might want to change CalculateAddition.feature file, just to initiate update and to escape strange errors about NUnit.

20. Select some file from SpecFlowTest, Test -> Run -> Tests in Current Context

21. Test failed, check View Test Result Details







Select the No match stuff (shown red, only methods, no class) from the diagnostics and put it to Step Definitions source file: CalculateAddition.cs:

namespace
SpecFlowTest.StepDefinitions
 {

    [Binding]

    public
class CalculateAddition

     {

         [Binding]

        public
class StepDefinitions

         {

            [Given(@"I have got the right sum of 3 and 4")]
             public
void GivenIHaveGotTheRightSumOf3And4()
             {

                ScenarioContext.Current.Pending
();

             }

 
              [When(@"I press add")]

              public
void WhenIPressAdd()

              {
                 ScenarioContext.Current.Pending
();
              }

 
              [Then(@"the result should be 7 on the screen and in the model field")]
              public
void ThenTheResultShouldBe7OnTheScreenAndInTheModelField()
              {

                 ScenarioContext.Current.Pending
();

               }
         }
    }

}

22. Comment
all lines: ScenarioContext.Current.Pending(); In the red fragment above.

23. Set SpecFlowTest as StartUp Project




















24. Run SpecFlowTest, Ctrl + F5, the test should pass

25. Prepare SpecFlowTest to run coded UI test. Insert “start and close application” parts to StepDefinitions->CalculateAddition.cs, like this (marked with red):

[Binding]
public class CalculateAddition
 {


     // application under test holder, used for coded ui
    private static ApplicationUnderTest calcApplication;
    [BeforeScenario()]
    public
static void PrepareForTest()
    {
     //TODO: Organize and parameterize this properly

     // Starts application under test

    calcApplication
= ApplicationUnderTest.Launch(

 @"C:\al\dev\SpecFlow\SfAndCuiCalculator\SfAndCuiCalculator\bin\Debug\SfAndCuiCalculator.exe",

 @"C:\al\dev\SpecFlow\SfAndCuiCalculator\SfAndCuiCalculator\bin\Debug\SfAndCuiCalculator.exe");

     }


     [AfterScenario] public void CleanUpTest()
    {

        //Closes Application under test

       calcApplication.Close
();
    }

In SpecFlowTest project, add (or check if added) Reference dll for ApplicationUnderTest class:
Microsoft.VisualStudio.TestTools.UITesting.dll. Resolve using stuff, if necessary.

26. Run SpecFlowTest, Ctrl + F5. Calculator should start and close.


27. Let’s add Coded UI Test invocation to SpecFlowTest.
Add the following to CuiCalculateAddition.cs (marked with red):

[CodedUITest]
public
class CuiCalculateAddition

 {

    public
static void Run() 

   {
        new
CuiCalculateAddition().CodedUITestMethod1();

    }

 
Add the following to StepDefinitions->CalculateAddition.cs (marked with red):


[Given(@"I have got the right sum of 3 and 4")]
public
void GivenIHaveGotTheRightSumOf3And4()
 {

    CuiCalculateAddition.Run
();
 
    //ScenarioContext.Current.Pending();
}


Add CodedUITest reference to SpecFlow, resolve using issues, if any.


28. Run SpecFlowTest, Ctrl + F5. Calculator should start. Coded UI Test should be completed from SpecFlow step. Calculator should close.

29. Now you can add some logic to other steps of SpecFlow according to your needs. The general idea is “to perform ui testing with Coded UI Test, then obtained results can be used to perform common Unit Testing as a part of Behavior Driven Development”. E.g Coded UI Test can be used to test View, then obtained states can be used to run unit tests on Model.
If you’ve got any questions, let me know.