Tuesday, 2 June 2015

selenium Webdriver script with SpecFlow and Visual Studio



SpecFlow is the .Net version of Cucumber. This is a Behavior development framework for .Net. Here we will show how we can implement our Selenium Webdriver script using SpecFlow framework.

Test Case : Verify the search Functionality of Google Search page
  • Open the browser and navigate to “www.google.com”.
  • Enter the word “SpecFlow” as Search Text.
  • Click on Search button.
  • Verify the search result.

Step One : Installing IDE integration package for SpecFlow 
  • Open Visual Studio and go to Tools>>Extension and Updates…
 
  • Extensions and Update window is displayed. Enter the word “SpecFlow” at search text box and press enter from keyboard. “SpecFlow for Visual Studio 2013” package is displayed as Search Result.
  • If you see Disable and Uninstall button then it means it is already installed with your IDE like the following.

  • If you see Download button then Click on this button.


  • It starts downloading.


  • After finishing download,click on Install button.


  • After finishing installation, click on Restart Now button.

  • Visual Studio will be restarted and if you go to Tools>>Extension and Updates… and search with “SpecFlow” then you see “SpecFlow for Visual Studio 2013” is installed.
  • In the same way search the extensions “NUnit Test Adapter” and Download it. It is used for NUnit Framework.

  • Click on Install button.

  • Click on Restart Now button to restart Visual Studio.


Step Two : Crating a new project with Unit Test Framework
  • Click on File menu and go File>>New>>Project

  • New project window is displayed.
  • Select Visual C#
  • Select Test
  • Select Unit Test Project


  • Enter project name as “GoogleSearchTest”
  • Select Location. In my case “D:\Development\”.
  • Select Solution name. In my case Solution name is same as Project name.
  • Check Create Directory for solution
  • Click on OK button.

  • “GoogleSearchTest” project is created.

Step Three : Add SpecFlow  reference from nuget.org
  • Go to Solution Explorer and Right click on Reference and click on Manage NuGet Packages…

  • Manage NuGet Packages window is displayed.
  • Enter the text SpecFlow at search text box and press enter from Keyboard.
  • SpecFlow package is displayed at Search list.
  • Click on Install button.
  • Installation Started.
  • After finishing installation, a green color icon is displayed and shown that SpecFlow is installed.
  • In the same way, we need to add SepcFlow.NUnit package.
  • Clicking on Install button will install this package.
Step Four : Add Selenium Webdriver reference from nuget.org
  • Enter the text Selenium WebDriver at search text box and press enter from Keyboard




  • Selenium WebDriver package is displayed at Search list.




  • Click on Install button.




  • Latest WebDriver will be installed and added as Reference.



  • Select Selenium WebDriver Support Classes package and click on Install button.
    • After finishing installation and click on Close button to close the Package Manager window.
    • Now verify that all the References are showing properly at the solution explorer.


    Step Five : Create a Feature file and write test case steps using gherkin syntax
    • Right click on the Project and go to Project>>Add>>New Item.
    • Add New Item window displayed.
    • Select Visual C# Items.
    • Select SpecFlow Feature File.
    • Enter file name as “GoogleSearchFeature.feature”. Note that Feature file name must have the extension “.feature”.
    • Click on Add button.

    • New Feature file is added with the project.
    • Double click on the File name “GoogleSearchFeature.feature” and File is opened at the Editor with default text.
    • Write the Feature name as “GoogleSearch”. Remove all the default text from Feature section.
    Feature: GoogleSearch
    • Write the case title as the scenario.
    Scenario: Verify the search Functionality of Google Search page
    • Write the test case steps using Gherkin syntax (Given…GoogleSearchWhen…Then).
    Given : It describes the precondition to execute test steps.
    When : It describes the steps to perform the test.
    Then : It describes the expected result. 
    In our case, Given clause will be,
    Given I navigate to the page "www.google.com"
    And I see the page is loaded
    Note that we an “And” operator to write multiple clauses. 
    When clause will be,
    When I enter Search Keyword in the Search Text box
    | Keyword  |
    | SpecFlow |
    And I click on Search Button
    Note that here we write data table for search keyword where we use “Keyword” as the table column name and “SpecFlow” is the data. 
    Then clause will be,
    Then Search items shows the items related to SpecFlow
    Now the Feature file looks like, 
    Step Six : Write code for every step
    • Here we write code for every Feature file steps.
    • In Order to write code we need Add a step definition class.
    • Right click on the Project and go to Project>>Add>>New Item
    • Add New Item window is displayed.
    • Select Visual C# Items.
    • Select SpecFlow Step Definition
    • Enter file name as “GoogleSearchFeatureSteps.cs”.
    • Click on Add button.
    • New class file is added with the project named “GoogleSearchFeatureSteps.cs”.
    • Go to GoogleSearchFeature.feature file.
    • Right click on Feature name and click on Generate Step Definitions
    • Generate Step Definition Skeleton window is displayed.
    • Click on Copy Methods to clipboard button and window is closed.
    • Go to GoogleSearchFeatureSteps.cs class. Remove all the sample codes from the class and it looks like the following.

    • Right click on the editor and paste the code on GoogleSearchFeatureSteps class.GoogleSearchFeatureSteps.cs class looks like the following. 
    • Now we need to write automated scripts for every steps
    • We need to add the following name space at GoogleSearchFeatureSteps.cs class.
    • Go to GoogleSearchFeature.feature file.
    • Right click on the First line of Given clause and click Go to Step Definition.

    • Note that  GoogleSearchFeatureSteps.cs file is opened and mouse cursor is blinked on the Given method. Also note that method name is the combination of all word of Given clause.

    • Write the code for GivenINavigateToThePage() method.
    Note that we do not need to write any comment here as Methods name describes the steps. This is the contribution BDD.
    • Write code for GivenISeeThePageIsLoaded() method.

    Here we just verify that appropriate page is loaded.
    • Write code for WhenIEnterSearchKeywordInTheSearchTextBox() method.


    Note that we use list of data in our feature file that SpecFlow converts to table. We can use it as normal Row/Column concept.
    • Write code for WhenIClickOnSearchButton() method.
    • Write code for ThenSearchItemsShowsTheItemsRelatedToSpecFlow() method.

    • GoogleSearchFeatureSteps.cs class looks like the following,

    Step Seven : Run the test
    • Delete default class UnitTest1.cs as it is not needed.

    • Build the solution by going to Build>>Build Solution.
    • Go to Test>>Windows>>Test Explorer
    • Note that the scenario name is the test name VerifyTheSearchFunctionalityOfGoogleSearchPage
    • Right click on the test name and click on Run Selected test.

    • Test will run using NUnit and Passed.

    • Click on Output link.
    • We see the output step by step as it is written in our Feature file.

    This is the power of SpecFlow using BDD.
    Lot more new things are coming…

    Monday, 11 May 2015

    Creating .CAB files with Powershell


    Syntax for creating a cab file
    New-CabinetFile -Name MyCabinet.cab -File "File01.exe","File02.txt"
    --This creates a new MyCabinet.cab file in the current directory and adds the File01.exe and File02.txt files to it, also from the current directory.
    Syntax for extracting a cab file
    Get-ChildItem C:\CabFile\ | New-CabinetFile -Name MyCabinet.cab -DestinationPath C:\Users\UserA\Documents
    --This creates a new C:\Users\UserA\Documents\MyCabinet.cab file and adds all files within the C:\CabFile\ directory into it.
    Code for the New-CabinetFile function:
    function New-CabinetFile {
        [CmdletBinding()]
        Param(
            [Parameter(HelpMessage="Target .CAB file name.", Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
            [ValidateNotNullOrEmpty()]
            [Alias("FilePath")]
            [string] $Name,
            [Parameter(HelpMessage="File(s) to add to the .CAB.", Position=1, Mandatory=$true, ValueFromPipeline=$true)]
            [ValidateNotNullOrEmpty()]
            [Alias("FullName")]
            [string[]] $File,
            [Parameter(HelpMessage="Default intput/output path.", Position=2, ValueFromPipelineByPropertyName=$true)]
            [AllowNull()]
            [string[]] $DestinationPath,
            [Parameter(HelpMessage="Do not overwrite any existing .cab file.")]
            [Switch] $NoClobber
            )
        Begin { 
            ## If $DestinationPath is blank, use the current directory by default
            if ($DestinationPath -eq $null) { $DestinationPath = (Get-Location).Path; }
            Write-Verbose "New-CabinetFile using default path '$DestinationPath'.";
            Write-Verbose "Creating target cabinet file '$(Join-Path $DestinationPath $Name)'.";
            ## Test the -NoClobber switch
            if ($NoClobber) {
                ## If file already exists then throw a terminating error
                if (Test-Path -Path (Join-Path $DestinationPath $Name)) { throw "Output file '$(Join-Path $DestinationPath $Name)' already exists."; }
            }
            ## Cab files require a directive file, see 'http://msdn.microsoft.com/en-us/library/bb417343.aspx#dir_file_syntax' for more info
            $ddf = ";*** MakeCAB Directive file`r`n";
            $ddf += ";`r`n";
            $ddf += ".OPTION EXPLICIT`r`n";
            $ddf += ".Set CabinetNameTemplate=$Name`r`n";
            $ddf += ".Set DiskDirectory1=$DestinationPath`r`n";
            $ddf += ".Set MaxDiskSize=0`r`n";
            $ddf += ".Set Cabinet=on`r`n";
            $ddf += ".Set Compress=on`r`n";
            ## Redirect the auto-generated Setup.rpt and Setup.inf files to the temp directory
            $ddf += ".Set RptFileName=$(Join-Path $ENV:TEMP "setup.rpt")`r`n";
            $ddf += ".Set InfFileName=$(Join-Path $ENV:TEMP "setup.inf")`r`n";

            ## If -Verbose, echo the directive file
            if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
                foreach ($ddfLine in $ddf -split [Environment]::NewLine) {
                    Write-Verbose $ddfLine;
                }
            }
        }
        Process {
             ## Enumerate all the files add to the cabinet directive file
            foreach ($fileToAdd in $File) {
                ## Test whether the file is valid as given and is not a directory
                if (Test-Path $fileToAdd -PathType Leaf) {
                    Write-Verbose """$fileToAdd""";
                    $ddf += """$fileToAdd""`r`n";
                }
                ## If not, try joining the $File with the (default) $DestinationPath
                elseif (Test-Path (Join-Path $DestinationPath $fileToAdd) -PathType Leaf) {
                    Write-Verbose """$(Join-Path $DestinationPath $fileToAdd)""";
                    $ddf += """$(Join-Path $DestinationPath $fileToAdd)""`r`n";
                }
                else { Write-Warning "File '$fileToAdd' is an invalid file or container object and has been ignored."; }
            }       
        }
        End {
            $ddfFile = Join-Path $DestinationPath "$Name.ddf";
            $ddf | Out-File $ddfFile -Encoding ascii | Out-Null;
            Write-Verbose "Launching 'MakeCab /f ""$ddfFile""'.";
            $makeCab = Invoke-Expression "MakeCab /F ""$ddfFile""";
            ## If Verbose, echo the MakeCab response/output
            if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
                ## Recreate the output as Verbose output
                foreach ($line in $makeCab -split [environment]::NewLine) {
                    if ($line.Contains("ERROR:")) { throw $line; }
                    else { Write-Verbose $line; }
                }
            }
            ## Delete the temporary .ddf file
            Write-Verbose "Deleting the directive file '$ddfFile'.";
            Remove-Item $ddfFile;
            ## Return the newly created .CAB FileInfo object to the pipeline
            Get-Item (Join-Path $DestinationPath $Name);
        }
    }

    Wednesday, 6 May 2015

    unexpected popups handling in CodedUI

    A lot of times, while running a UI test, our test runs into an unexpected page\state, say an unexpected error dialog, or an pop-up window, which would make our test fail and if that happens, rather than having the test rerun from the start, all we want is for it to resume when the page is loaded.
    I am taking the example of a winforms application with an alert window. The steps would be no different if you were trying the same on any other supported technology.
    Suppose let me say upon clicking a button there was an unexpected pop-up appearing. This pop-up blocks my TestMethod and makes it fail as it will not be able to perform any action as per the TestMethod. In this case these are the following steps which are to be followed
    1. Set a retry count- Playback.PlaybackSettings.MaximumRetryCount, i.e. you can specifiy the number of times you want a failed action to be retried. This is not a mandatory argument, if no value is set, the default value will be 1.
    2. Add a retry handler for the failed step. This is nothing but the handler function which will get called in case of a failure. You can add\remove this handler for any step in the coded UI test method, or even in test\class initialize as a generic handler for all failures.
    3.                         Playback.PlaybackError += Playback_PlaybackError;
    4. The handler method signature is as shown below
        1. private void Playback_PlaybackError(object sender, PlaybackErrorEventArgs e)
                  {
                      Console.WriteLine("Retrying .... ");
                        // By default, the exception will be thrown. Over here we are switching to retry mode.
                        e.Result = PlaybackErrorOptions.Retry;
                          // Just a simple enter to dismiss the Alert. If you are sure of any specific properties for
                          // a popup dialog or any other specific action you need to do, this is the place to 
                          // implement them.
                          Keyboard.SendKeys("{Enter}");
                      }
          1. Now simply setting the PlaybackErrorOptions to Retry will retry your failed step over and over until either the step passes or the MaximumRetryCount is hit. If you want to do any special handling, like say dismissing an alert, you can add the code for the same within the handler.
          2. TestMethod code looks like below
              TestMethod()
                      {
                          using (ApplicationUnderTest aut = ApplicationUnderTest.Launch("UnexpectedPopupAut.exe"))
                          {
                              #region Variable Declarations
                              #endregion
              // Important to set the MaximumRetryCount count for the retry handler to be invoked.
                              Playback.PlaybackSettings.MaximumRetryCount = 3;
                              // Add the error handler.
                              Playback.PlaybackError += Playback_PlaybackError;
              //Code of your TestMethod
                              Playback.PlaybackError -= Playback_PlaybackError;
            This is supported only for the following exceptions:-
            1. PlaybackFailureException
            2. UITestControlNotFoundException
            3. UITestControlNotAvailableException
            4. TechnologyNotSupportedException
            5. InvalidUITestExtensionPackageException
            6. DecodingFailedException
            7. FailedToPerformActionsOnBlockedControlException
            8. FailedToPerformActionsOnHiddenControlException
            9. UITestControlNotVisibleException
            10. ValidationFailedException
            11. FailedToLaunchApplicationException
            12. ActionNotSupportedOnDisabledControlExcept