Category: Pipeline

First Post as an Automation Engineer

As you probably don’t know, I have been given the new title of Automation Engineer. I haven’t really been doing much automation besides a short demo project I gave a brief presentation on. When, I got the green light to shuck some of my production development duties, as I am still an active Production Developer, and concentrate on automation I decided to start with an analysis of the current automation framework.

My first task was to review the code of our junior developer (now a very competent developer “sans junior”). He was hired as part of our grad program and was tasked with automating UI tests for our public facing websites. We didn’t have any real UI automation before he started working on it so there was no framework to draw from and he was basically shooting from the hip. He has been guided by our dev manager and has received some input from the team, but he was basically given a goal and turned loose.

He actually did a great job, but having no experience in automation there were bound to be issues. This would even hold true for the most seasoned developer. This post is inspired by a code review of his code. First let’s set some context. We are using Selenium WebDriver, SpecFlow, NUnit, and the Page Object Model pattern. I can’t really show any code as its private, but as you will see from my brain dump below that it allowed me to think about some interesting concepts (IMHO).

Keep Features and Scenarios Simple

I am no expert on automated testing, yet, but in my experience with UI testing and building my personal UI test framework project, features and scenarios should be as simple as possible especially when they need to be reviewed and maintained developers and non-techies. To prevent their eyes from glazing over at the site of hundreds of lines of steps, simplify your steps and focus your features. You should always look to start as simple as possible to capture the essence of the feature or scenario. Then if there is a need for more complexity negotiate changes and more detail with the stakeholders.

Focus on Business Functionality, Not Bug Hunting

Our grad used truth tables to draw out permutations of test data and scenarios. He wrote a program that generates all of the feature scenarios and did a generic test fixture that could run them. The problem is this results in thousands of lines of feature specifications that no one is going to read and maintaining them would be a nightmare. There is no opportunity to elicit input from stakeholders on the tests and the value associated with that collaboration is lost. Don’t get me wrong, I like what he did and it was an ingenious solution, but I believe the time he spent on it could have been better served producing tests that could be discussed with humans. I believe he was focused on catching bugs when he should have focused more on proving the system works. His tool was more for exploratory testing when what we need right now is functional testing.

Improve Cross Team Collaboration

It is important for us to find ways to better collaborate with QA, the business, IT, etc. BDD style tests are an excellent vehicle to drive collaboration as they are easy to read and understand and they are even executable by tools like SpecFlow. Additionally, they provide a road map for work that devs need to accomplish and they provide an official definition of done.

Focus, Test One Thing

It is important to separate test context properly. Try to test one thing. If you have a test to assert that a customer record can be viewed don’t also assert that the customer record can be edited as these are two separate tests.

In UI test, your Given should set up the user in the first relevant point of the workflow. If you are testing a an action on the Edit Vendor page, you should set the user up so they are already on the Edit Vendor page. Don’t have steps to go from the login to the View Vendor page and eventually Edit Vendor page as this would be covered in the navigation test of the View Vendor page. Similarly, if I am doing a View Vendor test I would start on the View Vendor page and if I wanted to verify my vendor edit links works, I would click one and assert I am on the Vendor Edit page, without any further testing of Vendor Edit page functionality. One assert per test, the same rules as unit tests.

Limit Dependencies

It may be simpler to take advantage of the FeatureContext.Current and ScenarioContext.Current dictionaries to manage context specific state instead of static members. The statics are good in that they are strongly typed, but they clutter the tests and make it harder to refactor methods to new classes as we have to take the static dependency to the new class when we already have the FeatureContext and ScenarioContext dependency available in all step bindings.

Test Pages and Controls in Isolation

Should we define and test features as a complete workflow or as discrete pieces of a configurable workflow. In ASP.Net web forms, a page or control has distinct entry and exit points. We enter through a Page request and exit through some form of redirect/transfer initiated by a user gesture and sometimes expressed in an event. In terms of the logic driving the page on the server, the page is not necessarily aware of its entry source and may not have knowledge of its exit destination. Sometimes a Session is carried across pages or controls and the Session state can be modified and used in a way that it has an impact on some workflows. Even in this situation we could setup Session state to a known value before we act and assert our scenario. So, we should be able to test pages/controls in isolation without regard to the overall workflow.

This is not to say that we should not test features end to end, but we should be able to test features at a page/control level in isolation. The same way we test individual logic units in isolation in a Unit Test. I would think it would be extremely difficult to test every validation scenario and state transition across an entire workflow, but we can cover more permutations in an isolated test because we only have to account for the permutations in one page/control instead of every page/control in a workflow.

Scope Features and Scenarios

I like how he is name spacing feature files with tags.

@CustomerSite @Vendor @EditVendor
Feature: Edit Vendor…

@EditVendor
Scenario:…

In this example there is a website called Customer Site with a page called Vendor and a feature named Edit Vendor. I am not sure if it is necessary to extend the namespace to the scenarios. I think this may be redundant as Edit Vendor covers the entire feature and every scenario included in it. Granted he does have a mix of context in the feature file (e.g. Edit Vendor and Create Vendor) and he tags the scenarios based on that context of the scenario. As, I think about it more, it may be best to actually extend the entire namespace to the scenario level as it gives fine grained control of test execution as we can instruct the test runner to only run certain tags. (Actually, I did a post on scoping with tags).

Don’t Duplicate Tests

Should we test the operation of common grid functionality in a feature that isn’t specifically about the grid. I mean if we are testing View Customers, is it important to test that the customer grid can sort and page? Should it be a separate test to remove complexity from the View Customer test? Should we also have a test specifically for the Grid Control?

In the end, he did an awesome job and laid a good solid foundation to move our testing framework forward.

Multiple PostBacks in ASP.NET WebForms

Here are some, not all, reasons why there would be multiple PostBacks on a page:

  • Handling an event multiple times
    • AutoEventWireup = true in Page declaration and manual wire up event in Page Init. Check your codebehind for the old ASP.Net 1 style of registering events in system generate code.
    • Having control’s AutoPostBack = true while also doing an explicit PostBack in another control event.
  • Custom event JavaScript that doesn’t cancel the click event allowing a double post.

Debugging tips:

  • Do an HTTP trace to view the double PostBack requests.
  • Debug and add watch for Request.Form[“__EVENTTARGET”] to find control initiating PostBack.
  • HTML Validate your page, PostBack could be caused by bad markup

Lastly, this is a little hack that may help turn off double PostBacks temporarily.

     <form id=”Form1″ runat=”server” onsubmit=”Q++; if(Q==1){return true;} else { return false;}”>

Common SpecFlow Steps

To share steps across features you have 2 options that I know of so far. You can create a class that inherits from SpecFlow.Steps, give it a [Binding] attribute, and code steps as normal and they will be usable in all features in the same assembly. This is inherent in the global nature of steps in SpecFlow and you don’t have to do anything to get this behavior.

When you need to share steps across assemblies it gets a little hairy. Say you want a common set of steps that you use for every SpecFlow feature that you write in your entire development life. To do this you will need a bit of configuration. You would create your Common SpecFlow Steps project, create a step class like you did above, reference this project in the test project you want to use it in, then add this little number to the <specflow> section in your configuration file:

<stepAssemblies>

  <stepAssembly assembly=”ExternalStepsAssembly” />

</stepAssemblies>

Just plug in the name of your Common SpecFlow Steps project and you are in business.

GUI Automation

I am building a browser automation framework with Selenium WebDriver, but there are things in the native browsers and the OS that I need to do that Selenium can’t help me with. Since most of my testing is in Windows I could just PowerShell it up, but I was wondering if there was something simpler. Well, I found these projects that I’d like to check out later:

http://www.sikuli.org/ – Sikuli automates anything you see on the screen. It uses image recognition to identify and control GUI components. It is useful when there is no easy access to a GUI’s internal or source code.

http://www.autoitscript.com/ – utoIt v3 is a freeware BASIC-like scripting language designed for automating the Windows GUI and general scripting. It uses a combination of simulated keystrokes, mouse movement and window/control manipulation in order to automate tasks in a way not possible or reliable with other languages (e.g. VBScript and SendKeys). AutoIt is also very small, self-contained and will run on all versions of Windows out-of-the-box with no annoying “runtimes” required!

I am not sure if these can provide the solution I am looking for. There are many more out there, but I already suffer from information overload so one day I will get to work evaluating these.

Selenium WebDriver File Download Testing

Not easy!

When you click a download button with the standard browser configuration you are asked for a location to download the file. Let’s explore the Google Encyclopedia  of copy and paste code to see how we can solve this.

The main solution seems to be setting the browser profile to automatically download without asking for a location. Below I have a little info on what I found out about Firefox, Chrome and IE. I didn’t do a deep dive. Right now I am spiking a solution to see if this will need to be a manual test.

Firefox

From our friends at StackOverflow this posts advocates manually setting the Firefox profile then changing to the profile in Selenium (http://stackoverflow.com/questions/14645877/how-to-test-downloading-files-in-selenium2-using-java-and-then-check-the-downloa)

In firefox also you can do the same thing.

Create one firefox profile

    Change the firefox download setting as it should save files without asking about location to save

    Launch the automation using that profile.

    FirefoxProfile profile = new FirefoxProfile(profileDir);

    driver=new FirefoxDriver(profile);

Another little gem from the same site says I can do one better by configuring the profile in code (http://stackoverflow.com/questions/16746707/how-to-download-any-file-and-save-it-to-the-desired-location-using-selenium-webd):

firefoxProfile.setPreference(“browser.helperApps.neverAsk.saveToDisk”,”text/csv”);

And this post brings it home and puts it all together (http://stackoverflow.com/questions/1176348/access-to-file-download-dialog-in-firefox)

FirefoxProfile firefoxProfile = new FirefoxProfile();

    firefoxProfile.setPreference(“browser.download.folderList”,2);

    firefoxProfile.setPreference(“browser.download.manager.showWhenStarting”,false);

    firefoxProfile.setPreference(“browser.download.dir”,”c:\\downloads”);

    firefoxProfile.setPreference(“browser.helperApps.neverAsk.saveToDisk”,”text/csv”);

    WebDriver driver = new FirefoxDriver(firefoxProfile);//new RemoteWebDriver(new URL(“http://localhost:4444/wd/hub&#8221;), capability);

driver.navigate().to(“http://www.myfile.com/hey.csv&#8221;);

Chrome

There are instructions on achieving the same results as Firefox, but you have to jump threw a few minor hoops to get there (http://stackoverflow.com/questions/15824996/how-to-set-chrome-preferences-using-selenium-webdriver-net-binding).

IE

There seems to be ways to do this in WatiN in browsers below IE9, but for current IE browsers its just plain ugly (http://stackoverflow.com/questions/7500339/how-to-test-file-download-with-watin-ie9/8532222#8532222). I guess I could use one of the GUI Automation tools (see GUI Automation post), but is it really worth all that?

I haven’t tried these at home, so I am naively assuming that they work. Anyway after you have successfully downloaded  the file, you can use C# System.IO to inspect the file format, size, file name, content…you get the picture.

SpecFlow Manual Testing

Sometimes there are scenarios that can only be tested manually. Maybe you are testing colors or placement of a picture or some other important feature that only human eyes can assert as right or wrong. When I have a manual test definition in my automated test framework I want to tell the framework to ignore it, but still report it so we don’t lose sight of it. I am building features into my test framework to handle ignoring manual testing, but I found this code below that does it easily in SpecFlow.

[Binding, Scope(Tag = “Manual”)]
public class ManualSteps
{
    [Given(“.*”), When(“.*”), Then(“.*”)]
    public void EmptyStep()
    {
    }

    [Given(“.*”), When(“.*”), Then(“.*”)]
    public void EmptyStep(string multiLineStringParam)
    {
    }

   [Given(“.*”), When(“.*”), Then(“.*”)]
    public void EmptyStep(Table tableParam)
    {
    }
}

From https://github.com/techtalk/SpecFlow/wiki/Scoped-Bindings

With this any scenario tagged with @Manual will be ignored, but they will still be reported in the test report. Sweet.

SpecFlow Ambiguous Step Definitions

It’s been a long time since I posted anything. I have a ton of material to post, just been too busy or lazy to post it.

Anyway, here is the problem. I use SpecFlowSelenium WebDriver, and the Page Object Model pattern to implement UI tests. I want to scope my SpecFlow Step Definitions and I ran into this link that made me think twice about doing it. https://github.com/cucumber/cucumber/wiki/Feature-Coupled-Step-Definitions-%28Antipattern%29

The basic premise is that you shouldn’t tie your step definitions to features.

Feature-coupled step definitions are step definitions that can’t be used across features or scenarios. This is evil because it may lead to an explosion of step definitions, code duplication and high maintenance costs.

I can agree with this, but there should be a way to tie a step to a context. The best example of what I mean is when a step is only relevant to a page or control when doing UI tests. When you have a generic step definition, but the implementation can be specific to a page or control it makes sense to be able to scope the step to the page or control.  For example, if we take the scenario from the wiki page above

Scenario: add description
  Given I have a CV and I’m on the edit description page
  And I fill in “Description” with “Cucumber BDD tool”
  When I press Save
  Then I should see “Cucumber BDD tool” under “Descriptions”
(Note: Save is a regular expression on the wiki, but I rely on page object models so it isn’t necessary to pass the value to the step method as my actions are explicit.)

The “When I press Save” step is going to call a method in a page object to actually press the Save button. The step will use a specific page object to execute the step and this generic definition does not provide any context to say which page object to use. If I could scope the step definitions and implementations to a particular page or control, I could have various implementations to target various page objects to drive the page or control under test.

With this we are not coupling by feature, but by page or control. Is this bad or another anti-pattern? Time will tell, but I have had the hardest time trying to name steps with context identifiers to try to get around the problem of step definitions having a global scope in SpecFlow. If I had another scenario that used the “When I press Save” definition, but is implemented with a different page object we run into ambiguity issues because SpecFlow doesn’t know which implementation to use. Without a scoping mechanism I have to add context to the step definitions. Our simple definition would become, “When I press Save on the CV Edit Description page”. This usually makes defining steps and reading them a lot harder than it should be because I have to use more words.

As a general practice, I normally scope my features and scenarios with a tag indicating the page or control under test and this could easily be used in the step definitions to couple step implementations to specific pages and controls. With SpecFlow we can use a feature called Scoped bindings to achieve page/control scoped step definitions.

The Scope Attribute can be used to restrict the execution of step definitions by features, scenario, or by tag. Since scoping by feature is an anti-pattern we won’t use that one. The scenario is a viable restriction, but I believe tag will provide the most flexibility as we can restrict multiple scenarios across various features without limiting the step to a particular feature or scenario. Although, there is the problem of tags only being applied at the scenario level. We can not tag a scenario step in SpecFlow, i.e. tag the Given, When and Then separately. I am not sure if this would be necessary. I have to get more specs written with scoped bindings to see what troubles I run into.

You can look at the Scoped bindings link for usage, but in our scenario above we could use this technique by tagging the scenario with the page name:

@CVEditDescription
Scenario: add description
  Given I have a CV and I’m on the edit description page
  And I fill in “Description” with “Cucumber BDD tool”
  When I press Save
  Then I should see “Cucumber BDD tool” under “Descriptions”

Then the “When I press Save” step can be scoped to the CV Edit Description page like so:

[When (@”I press Save”, Scope(Tag = “CVEditDescription”)]
public void WhenIPressSave()
{
     //Call Save on the page object
     cvEditDescriptionPage.Save();
}

We also get the added benefit of being able to run tests just for this page (tag). So far I like it. How do you solve ambiguity issues in SpecFlow?

Formalized Versioning

Phil Haack did a post about SemVer 2.0, a formal specification for public API versioning. I think it’s a novel idea as it puts a name and formal structure to what a lot of dev shops I know have been doing. It also allows packaging tools to standardize, like the work Phil talks about with NuGet.

I have added “integrating SemVer and NuGet into CI” to my very long list of things to do for my main side project. That list just keeps on growing.

I Can’t Reproduce That

Sorry, I can’t reproduce that.

I hate saying those words. It seems like a cop out, like I am giving up on the problem. How do you tell someone that you can’t reproduce their issue? Do you ask for more details? Do you just leave it up to the user because you think it is an isolated user issue?

I always ask for more info. The problem is sometimes I don’t know what to ask for. On a web app, if I don’t get an error log I have to ask for browser info from the user and this is an exercise in and of itself. I need to be aware of browser plugins, state of cache (last time cleared), the user and steps used to trigger the issue… and more. After I get the basics necessary for most browser based issues, I start asking more questions specifically related to the scenario that is bombing. Here in lies the problem. Asking users for info usually results in surface data that don’t help get down to the nuts and bolts of the problem. Also, I don’t have a test lab readily available to me so spinning up a browser configured like the user is not possible.

It is hard to get the info you need without stepping through a debug session to see what is going on.  I sometimes have to result to adding additional instrumentation to code to hopefully get better error messages or state info, but this requires a push to production and the user having to wait until all of this is done. So, how can I analyze an issue without this information?

I know there are solutions out there that will record live user sessions in production and even record the stack trace down to the method that caused the issue. Unfortunately, I don’t have access to any of these tools. I guess I will have to just get better at asking questions that even tech illiterate users can follow.

IIS HTTP Error 503. The service is unavailable.

Today I received an error while trying to browse an ASP.NET website application locally, “HTTP Error 503. The service is unavailable.”

Fortunately, I found an excellent post on troubleshooting IIS issues, Troubleshooting IIS7 503 “Service unavailable” errors with startup debugging by Mike Volodarsky. I am just documenting some of the things that were a little different for me. I am running Windows 7 and IIS 7. I downloaded Windows Software Development Kit (SDK) for Windows 8 from http://msdn.microsoft.com/en-US/windows/hardware/hh852363 and only installed the debugger to the default location. This made the path to the debugger executable  C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\ntsd.exe. I used regedit to add the w3wp.exe Registry Key (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\w3wp.exe) with the Debugger string value of C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\ntsd.exe -server npipe:pipe=w3wp -g. I also added C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\windbg.exe to my Path to make it easy to start in command line.

Unfortunately, I didn’t need to go through all of that. I never got the debugger to attach because the Worker Process wouldn’t start. After some experimenting I decided to change the Application Pool for my web application and the app came up. I looked at the old Application Pool and noticed something that didn’t hit me before. I spent 2 hours researching and poking around and my real error in this instance was the Application Pool I created for my web application was assigned to my local Windows account. When I was forced to update my password the password did not update on the Application Pool. So, updating the password fixed my issue. I have since created a new Windows account specifically for this web app that doesn’t have a password that expires.

Anyway, it was a nice exercise getting windbg up and running. Maybe I will really need it one day.

Fun Stuff!

*Safety Note: Use the Windows Debugger Install instructions above at your own risk. It may affect your Visual Studio Debugger.