Powered By Blogger

Search Here!

Friday, September 28, 2012

SpecFlow Error : Step bindings are still being analyzed. Please wait. !


I am having problems generating the step definitions. I'm using Visual Studio 2010 Professional fully patched.

My scenario tests do work, everything is "green". But when I want to navigate from a feature step to its binded method I get the error "Step bindings are still being analyzed. Please wait."


Solution: Clean the solution and then rebuild, it solved.

SpecFlow: Step Intellisense in VisualStudio !


SpecFlow is aiming at providing pragmatic BDD for .NET.

SpecFlow 1.5 comes with Intellisense for step-completion in VisualStudio 2010:



When you are writing feature files, you get Intellisense after Given/When/Then/And/But keywords.
As usual you can trigger Intellisense with Ctrl-Space.

The feature is switched off by default. You have to enable it under Menu –> Tools –> Options then choose SpecFlow. In the Editor Settings set 'Enable Intellisense' to True:



SpecFlow can be downloaded from GitHub.

Keep your SpecFlow flowing :)

Friday, September 14, 2012

WebDriver Handling Environment Slowness !

Best way to handle WebDriver code in the environment slowness. We have faced too many issues due to slow environment for our website, in night when usage gone down then WebDriver working perfectly but generally in day time when we have large usage then it’s very hectic to handle even for the perfectly written scripts.    

So, I used the pageLoadTimeout method that solves all the problem that we were facing due to environment slowness. I used in the WebDriver instance initiate so for each and every WebDriver command it always check for page load.

public static IWebDriver WebDriver
        {
            get
            {
                if (_webdriver == null)
                    _webdriver = GenericHelper.GetWebDriverInstance();
                _webdriver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromMinutes(2));
                return _webdriver;
            }
        }

You can use other methods also as per your use.

WebDriver.Timeouts
implicitlyWait(long time, java.util.concurrent.TimeUnit unit)
Specifies the amount of time the driver should wait when searching for an element if it is not immediately present.
WebDriver.Timeouts
pageLoadTimeout(long time, java.util.concurrent.TimeUnit unit)
Sets the amount of time to wait for a page load to complete before throwing an error.
WebDriver.Timeouts
setScriptTimeout(long time, java.util.concurrent.TimeUnit unit)
Sets the amount of time to wait for an asynchronous script to finish execution before throwing an error.

Sunday, September 2, 2012

WebDriver: Click Techniques !


There are number of techniques by which you can interact with web page. As Selenium tool - WebDriver is a very strong tool to interact with various elements on web page but sometimes we stuck in this and not able to understand why it is happening. If we are doing Automation it means, it would work in every condition and every environment. From my experience once time, my code is able to click an element on my local system but same code when running on taking system remote, it won't(we had the same environment on both the systems).

So, I mean there is a lack of interaction of WebDriver with web page when I was running it on remote system yes there was some network speed issue but we already used the ideal waits for elements.

I came to know that there were lots of JavaScript on page where I was generally getting issue due to JavaScript error(s) or due to lazy load of JavaScript on the webpage. Sometimes JavaScript fully loaded on the page sometimes not due to network speed on the remote system. As WebDriver itself is a JavaScript based tool, so could not go beyond that to avoid JavaScript based errors.

So, Following techniques helps you to click element on the page and various other actions too:

If page or pop up’s contains no JavaScript then we can use for click,

WebDriver.FindElement(By.Id("_ctl0_ContentHolderHeader_lbtnSavePrefHeader")).Click();

If page or pop up’s contains some JavaScript’s then we can use for click,

IWebElement isPageLoaded = WebDriver.FindElement(By.Id("ImgPoweredBy"));
isPageLoaded.Click();

If page or pop up’s contains possible more JavaScript and JavaScript’s Errors then we can use for click,

IWebElement menu = WebDriver.FindElement(By.XPath("//table[@id='GridStudent']/tbody/tr/td[2]/span"));
            Actions builder = new Actions(WebDriver);
            builder.Click(menu).Perform();

If page or pop up’s contains highly JavaScript’s and JavaScript’s Errors then we can use,

IWebElement menu = WebDriver.FindElement(By.XPath("//table[@id='GridStudent']/tbody/tr/td[2]/span")); 
((IJavaScriptExecutor)WebDriver).ExecuteScript("$(arguments[0]).click()",menu);

Tuesday, August 28, 2012

Continuous Integration: Generate SpecFlow Report with append Time Stamp !

This Batch code calls the MSTest latest trx file and convert it into SpecFlow HTML report and save it with appending Time Stamp  and copy the HTML file in other driver for public access. This we majorly implemented and used in the CI that calls this batch file through MSBuild Definition and execute the Batch Commands.


set SAVESTAMP=%DATE:/=-%@%TIME::=-%
set SAVESTAMP=SMOKERESULT_%SAVESTAMP: =%.html

for /f "delims=" %%x in ('dir /od /a-d /b E:\B2\TestResults\*.*') do set recent=%%x    //Path of the directory where trx file resides.

echo %recent%

REM Remove space from the file name here

set OldFileName=%recent%

set NewFileName=%OldFileName: =%

ren "E:\B2\TestResults\%OldFileName%" %NewFileName%

"C:\Program Files\TechTalk\SpecFlow\SpecFlow.exe" mstestexecutionreport E:\B2\Sources\PegasusBDD\PegasusTestScripts\PegasusTestScripts.csproj /testResult:E:\B2\TestResults\%NewFileName% /out:%SAVESTAMP%

echo %SAVESTAMP%

copy %SAVESTAMP% Z:\

Saturday, August 11, 2012

Running MSTest and SpecFlow Report from Batch File !


It is very hectic setup the code in different machines by changing the aap.config any hardcoded path again and again. This is not the actual thing for coding and very unprofessional. Lets we have a lines of batch code that get rid from this, just run the batch commands in order to run the MSTest Metadata file containing Unit Test(s) and generates SpecFlow report.

Earlier it was something like, hard coded strings

if Exist "C:\Users\manish.singh\Desktop\Code 14th march\QA Automation\Pegasus_BDD\Framework.ReportGeneration\TestResult.trx" del "C:\Users\manish.singh\Desktop\Code 14th march\QA Automation\Pegasus_BDD\Framework.ReportGeneration\TestResult.trx"
"C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe" /testcontainer:"C:\Users\manish.singh\Desktop\Code 14th march\QA Automation\Pegasus_BDD\Ordered_TestSuite\Pegasus_SpecFlow.OrderedTest.orderedtest" /resultsfile:"C:\Users\manish.singh\Desktop\Code 14th march\QA Automation\Pegasus_BDD\Framework.ReportGeneration\TestResult.trx"
"C:\Program Files\TechTalk\SpecFlow\SpecFlow.exe" mstestexecutionreport "C:\Users\manish.singh\Desktop\Code 14th march\QA Automation\Pegasus_BDD\PegasusTestScripts.csproj" /testresult:"C:\Users\manish.singh\Desktop\Code 14th march\QA Automation\Pegasus_BDD\Framework.ReportGeneration\TestResult.trx" /out:"C:\Users\manish.singh\Desktop\Code 14th march\QA Automation\Pegasus_BDD\Framework.ReportGeneration\MyResult.html"


Now change it into very generic fashion,


IF EXIST TestResult.trx DEL TestResult.trx

"C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\MSTest"
/testmetadata:../STTestList.vsmdi /testlist:STTestList
/resultsfile:TestResult.trx

"C:\Program Files\TechTalk\SpecFlow\SpecFlow.exe" mstestexecutionreport
../PegasusTestScripts/PegasusTestScripts.csproj /testResult:TestResult.trx
/out:MyResult.html

echo Created file MyResult.html

MyResult.html

Saturday, July 14, 2012

BDD Setting up with Event Definition using SpecFlow !

Event Definition helps us to run the test scripts or scenarios in the definite manner and pattern. I have run the scenarios as feature basis, when one feature completes then WebDriver stops and re-initiate when next feature starts whatever the number of scenarios it contain. This helps us to save the execution time and get the maximum throughput for our test suite. Below is the structure of event definition file,

[Binding]
    public class BaseTestScript
    {
        public static IWebDriver WebDriver = null;
        public static ISelenium BackedSelenium= null;
        public static SqlConnection DatConnection = DatabaseTools.GetSqlConnection();
        static readonly string Browser = ConfigurationManager.AppSettings["browser"];


        // Purpose: To Start WebDriver
        public static void WebDriverStart()
        {
            try
            {
                WebDriver.Navigate().GoToUrl(ConfigurationManager.AppSettings["browserUrl"]);
                Thread.Sleep(3000);
                WebDriver.FindElement(By.Id("ImgPoweredBy"));
                WebDriver.Manage().Window.Maximize();
                Thread.SetData(Thread.GetNamedDataSlot("webdriverInstance"), WebDriver);
                Thread.SetData(Thread.GetNamedDataSlot("backedseleniumInstance"), BackedSelenium);
            }
            catch (Exception e)
            {
                if (Browser != null) throw new TypeLoadException(Browser+" cannot display the webpage, Please Try Again");
            }
            Console.WriteLine("WebDriver Started");
        }

        // Purpose: To Stop WebDriver
        public static void WebDriverStop()
        {
            if (WebDriver == null)
                return;
            try
            {
                WebDriver.Manage().Cookies.DeleteAllCookies();
                WebDriver.Dispose();
                if (Browser.Equals("IE"))
                {
                    Process[] iexpPro = Process.GetProcessesByName("iexplore");
                    if (iexpPro.Length > 0)
                    {
                        foreach (Process clsProcess in iexpPro)
                        {
                            clsProcess.Kill();
                        }
                    }
                }
                if (Browser.Equals("Firefox"))
                {
                    Process[] fireFoxPro = Process.GetProcessesByName("firefox");
                    if (fireFoxPro.Length > 0)
                    {
                        foreach (Process clsProcess in fireFoxPro)
                        {
                            clsProcess.Kill();
                        }
                    }
                }
                if (Browser.Equals("Safari"))
                {
                    Process[] safariPro = Process.GetProcessesByName("safari");
                    if (safariPro.Length > 0)
                    {
                        foreach (Process clsProcess in safariPro)
                        {
                            clsProcess.Kill();
                        }
                    }
                }
                Process[] selcomwin = Process.GetProcessesByName("mshta");
                if (selcomwin.Length > 0)
                {
                    foreach (Process clsProcess in selcomwin)
                    {
                        clsProcess.Kill();
                    }
                }
                Process[] ieDriverserver = Process.GetProcessesByName("IEDriverServer");
                if (ieDriverserver.Length > 0)
                {
                    foreach (Process clsProcess in ieDriverserver)
                    {
                        clsProcess.Kill();
                    }
                }
            }
            catch (Exception e)
            {
                //throw new Exception("Unable To Stop WebDriver: Please Try Again.");
            }
            WebDriver = null;
            Console.WriteLine("WebDriver Stopped");
        }

        [BeforeTestRun]
        // Purpose: To Initialize TestScript
        public static void TestInitialize()
        {
            try
            {
                //Purpose: Opening DB Connection
                DatConnection.Open();
            }
            catch (Exception e)
            {
                throw new Exception("Unable To Open Database Connection: Please Try Again.");
            }
            //Purpose : Call Method To Select Browser
            BrowserSetup();
            //Purpose : Call Method To Start WebDriver
            WebDriverStart();
        }

        [AfterTestRun]
        // Purpose: To Dispose TestScript
        public static void TearDown()
        {
            try
            {
                //Purpose: Closing DB Connection
                DatConnection.Close();
            }
            catch (Exception e)
            {
                throw new Exception("Unable To Close WebDriver: Please Try Again.");
            }
            WebDriverStop();
            Thread.SetData(Thread.GetNamedDataSlot("webdriverInstance"), WebDriver);
            Thread.SetData(Thread.GetNamedDataSlot("backedseleniumInstance"), BackedSelenium);
        }

        //Purpose: Selecting Browser To Run Test
        public static void BrowserSetup()
        {
            if (Browser.Equals("IE"))
            {
                string ieDriverPath = ConfigurationManager.AppSettings["ieDriverPath"];
                var options = new InternetExplorerOptions { IntroduceInstabilityByIgnoringProtectedModeSettings = true };
                WebDriver = new InternetExplorerDriver(ieDriverPath, options);
                BackedSelenium = new WebDriverBackedSelenium(WebDriver, ConfigurationManager.AppSettings["browserUrl"]);
                BackedSelenium.Start();
            }
            if (Browser.Equals("Firefox"))
            {
                WebDriver = new FirefoxDriver();
                BackedSelenium = new WebDriverBackedSelenium(WebDriver, ConfigurationManager.AppSettings["browserUrl"]);
                BackedSelenium.Start();
            }
            if (Browser.Equals("Safari"))
            {
                WebDriver = new SafariDriver();
                BackedSelenium = new WebDriverBackedSelenium(WebDriver, ConfigurationManager.AppSettings["browserUrl"]);
                BackedSelenium.Start();
            }
        }
    }

WebdriverBackedSelenium in C# using WebDriver !

Using WebDriverBackedSelenium with different browser(s) setting contains the .NET bindings for the older, more procedural Selenium Remote Control (or Selenium RC) API, but implemented using the newer WebDriver technology. It does not require a running instance of the Selenium Server.

if (Browser.Equals("IE"))
            {
                string ieDriverPath = ConfigurationManager.AppSettings["ieDriverPath"];
                var options = new InternetExplorerOptions { IntroduceInstabilityByIgnoringProtectedModeSettings = true };
                WebDriver = new InternetExplorerDriver(ieDriverPath, options);
                BackedSelenium = new WebDriverBackedSelenium(WebDriver, ConfigurationManager.AppSettings["browserUrl"]);
                BackedSelenium.Start();
WebDriver.Navigate().GoToUrl(ConfigurationManager.AppSettings["browserUrl"]);

            }
            if (Browser.Equals("Firefox"))
            {
                WebDriver = new FirefoxDriver();
                BackedSelenium = new WebDriverBackedSelenium(WebDriver, ConfigurationManager.AppSettings["browserUrl"]);
                BackedSelenium.Start();
WebDriver.Navigate().GoToUrl(ConfigurationManager.AppSettings["browserUrl"]);
            }
            if (Browser.Equals("Safari"))
            {
                WebDriver = new SafariDriver();
                BackedSelenium = new WebDriverBackedSelenium(WebDriver, ConfigurationManager.AppSettings["browserUrl"]);
                BackedSelenium.Start();
WebDriver.Navigate().GoToUrl(ConfigurationManager.AppSettings["browserUrl"]);
            }

Tuesday, July 3, 2012

Using Scope Bindings with SpecFlow !

Hi, again I have learned a new thing in BDD using SpecFlow i.e. Scope Binding. Let’s take a look at how to do this with a very generic example. I’m going to be write tests for creating user and course, Create User and Create Course.  In both cases, I’m supposed to click on the link at the top of the page, although they’re different links that are the requirements are set in freeze, and will not re-write them as we can assume to understand the context based on the feature.
So, let’s write the add each feature and scenario.  We’re going to need two feature files.  One for checking the ‘Create New User’ link, and one for the ‘Create New Course’ link.

Feature: US58858 - User Creation
 In order to Creation of User 
 As a WS Admin
 I want to create user

Scenario: Create the new User using create user link 
Given I am on the User Creation Page
When  I clicked the link at top of the page
Then  I should see the "Create New User" popup
When  I create the user  with user details     
    | Field              | Value      |
    | txtLoginName       | Teacher    |
    | txtPassword        | pwd        
    | txtFirstName       | FN         |
    | txtLastName        | LN         |
    | txtEmail           | Email      |
Then  It should display successful message "New user created successfully."
And   I clicked on the Logout link to get logged out from the application

-------------------------------------------------

Feature: US58857 -  Course Creation
 In order to Creation of Course 
 As a WS Admin
 I want to create course(s) as a Empty Course, Container Course, Master Library 
and Master Course
Scenario Outline: Create the new Course using create course link
 Given I am on the Course Creation page
 When  I clicked the link at top of the page
 Then  I should see the "Create New Course" popup
 When  I creted the course as name with prefix 
 Then  It should display successful message "New course created successfully."
 Then  I should see the created  course
 Examples:
 | coursename |
 | BDDEC         |
 | BDDML        |
 | BDDCC         |
 | BDDMC       |
And  I clicked on the Logout link to get logged out from the application

Now, we’re going to add some context to each of these.  I’m going to add the @user tag to the scenarios in the US58858 - User Creation feature, while adding the @course tag to the scenarios in the US58857 -  Course Creation feature.

@user
Scenario: Create the new User using create user link 
Given I am on the User Creation Page
When  I clicked the link at top of the page
Then  I should see the "Create New User" popup
When  I create the user  with user details     
    | Field                          | Value        |
    | txtLoginName       | Teacher    |
    | txtPassword           | pwd           
    | txtFirstName         | FN              |
    | txtLastName         | LN              |
    | txtEmail                  | Email        |
Then  It should display successful message "New user created successfully."
And   I clicked on the Logout link to get logged out from the application
 --------------------------------------------------------------
@course
Scenario Outline: Create the new Course using create course link
 Given I am on the Course Creation page
 When  I clicked the link at top of the page
 Then  I should see the "Create New Course" popup
 When  I creted the course as name with prefix 
 Then  It should display successful message "New course created successfully."
 Then  I should see the created  course
 Examples:
 | coursename |
 | BDDEC           |
 | BDDML         |
 | BDDCC          |
 | BDDMC        |
And  I clicked on the Logout link to get logged out from the application
 
Now, let’s write the code for this the way that we normally would.  We can see that 
we have a builderror however.  This is because we have two of the exact same When’s.  
We need to find a way to separate these. We could, and should rewrite this, 
but as I said earlier, we were told that the way that they were written has to 
stay exactly as it was.  Instead, let’s use the Scope tags to add some context.  
The way that has worked best for me, is to start separating some of the code into folders, 
to keep everything organized.  We’re going to do this for the Create user and Create Course. 
Next, we’re going to add a stepdefinition file to each of those folders to help keep our 
code a little more organized.
Now that we have this setup, let’s write our When methods in their respective step 
definition files.  As a note, you can put any step definitions you want into any class 
so long as you add the [Binding] tagto the class.  Unless you have a need to duplicate code, 
I recommend only putting the steps that contain scope into these new classes, 
or at least, that’s what’s worked well for me so far.
 
 namespace Pegasus_SpecFlow
 {
 [Binding]
  public class CreateUserStepDefinitions : Helper
  {
 [When(@"I click the link at the top of the page")]
 public void WhenIClickTheLinkAtTheTopOfThePage()
 {
 Click(user);
 }
 }
 }
  
namespace Pegasus_SpecFlow
{
[Binding]
public class CreateCourseStepDefinitions : Helper
{
[When(@"I click the link at the top of the page")]
public void WhenIClickTheLinkAtTheTopOfThePage()
{
Click(course);
}
}
}
 
Now, we want to add our scope.  We can do this at the class level, or the step level.  
Normally, I would do this at the step level, but, as I was writing this, 
I learned that you can do this at the class level.
Scoped Binding at the class level
 
 namespace Pegasus_SpecFlow
 {
 [Binding]
 [Scope(Feature="US58858 - User Creation")]
 public class CreateUserStepDefinitions : Helper
 {
 [When(@"I click the link at the top of the page")]
 public void WhenIClickTheLinkAtTheTopOfThePage()
 {
 Click(user);
 }
 }
 }
OR
 
Scoped Binding at the method, or step level
 
namespace Pegasus_SpecFlow
{
[Binding]
public class CreateUserStepDefinitions : Helper
{
[When(@"I click the link at the top of the page"),
Scope(Tag="user")]
public void WhenIClickTheLinkAtTheTopOfThePage()
{
Click(user);
}
}
}
 
I’m pretty certain that our tests should run.  After a little bit of debugging, 
I make sure that my webdriver code works.  Then, find a way to make your test fail 
to ensure that it’s working correctly and you should be good to go.