*Updated* 21 March 2011: Updated how "Coded UI tests" finds a control with info from Balagans Blog - How does “Coded UI test” finds a control?
We need Web functionality tests!!! (and a lot of people are already doing them)
Reasons?
- Easier to find bugs
- No need for a lot of manual testing
- Maintainability of your code (THIS IS BIG!!)
- When we change something (Code, DB, scripts, HTML,...) we want to verify if our user stories working as expected
- We setup web tests for each user story that we have.
- We can use web tests in load tests or stress tests
- … lots more
Note from Wikipedia
Stress testing: Simulates increased load, more than expected
Load testing: End to end performance testing under anticipated load
I tried the following 3 players (recommendations from work mates, and others..)
All of these 3 tools provide a recording tool, where you can record your browsing actions and generate code from that.
This is important!!!
No one wants to write these tests manually!
Do the test recording
Selenium Test recorder just works.
Record your session. Copy & paste to Visual Studio. Done
Watin Test recorder v2 throw exception
Bug reported here: http://sourceforge.net/tracker/index.php?func=detail&aid=2934193&group_id=193118&atid=944137
Watin Test recorder V1 generates unsupported code -> manual fixing needed :-(
Code output of recorder
Figure: Simulating a user registration with Seleniumselenium.Open("/Public/default.aspx"); selenium.Click("//div[@id='userlogin']/div/div[2]"); selenium.Click("//div[@id='userstatusLoggedOut']/div/a/span"); selenium.WaitForPageToLoad("30000");
selenium.Type("ctl10_MainContentArea_ctl00_ctl00_CreateUserForm_CreateUserStepContainer_FirstName", "o"); selenium.Type("ctl10_MainContentArea_ctl00_ctl00_CreateUserForm_CreateUserStepContainer_LastName", "g"); selenium.Type("ctl10_MainContentArea_ctl00_ctl00_CreateUserForm_CreateUserStepContainer_Email", "peter@gfader.com"); selenium.Type("ctl10_MainContentArea_ctl00_ctl00_CreateUserForm_CreateUserStepContainer_ConfirmEmail", "peter@gfader.com"); selenium.Type("ctl10_MainContentArea_ctl00_ctl00_CreateUserForm_CreateUserStepContainer_Password", "password!"); selenium.Type("ctl10_MainContentArea_ctl00_ctl00_CreateUserForm_CreateUserStepContainer_ConfirmPassword", "password!"); selenium.Click("ctl10_MainContentArea_ctl00_ctl00_CreateUserForm___CustomNav0_StepNextButtonButton"); selenium.WaitForPageToLoad("30000");
selenium.Click("link=Log Out"); selenium.WaitForPageToLoad("30000");
IE ie = new IE("about:blank"); ie.GoTo("http://REMOVED.ssw.com.au/Public"); ie.Div(Find.ByCustom("innertext", "Member Login")).Click(); ie.Link(Find.ByUrl("http://REMOVED.ssw.com.au/Public/Profile/Register.aspx")).Click();
ie.TextField(Find.ByName("ctl10$MainContentArea$ctl00$ctl00$CreateUserForm$CreateUserStepContainer$FirstName")).TypeText("Peter"); ie.TextField(Find.ByName("ctl10$MainContentArea$ctl00$ctl00$CreateUserForm$CreateUserStepContainer$LastName")).TypeText("Gfader"); ie.TextField(Find.ByName("ctl10$MainContentArea$ctl00$ctl00$CreateUserForm$CreateUserStepContainer$Email")).TypeText("petermenuqggfader.com"); ie.TextField(Find.ByName("ctl10$MainContentArea$ctl00$ctl00$CreateUserForm$CreateUserStepContainer$Password")).TypeText("petermenuqggfader.com"); ie.TextField(Find.ByName("ctl10$MainContentArea$ctl00$ctl00$CreateUserForm$CreateUserStepContainer$Password")).TypeText("passmenumenuqword!"); ie.TextField(Find.ByName("ctl10$MainContentArea$ctl00$ctl00$CreateUserForm$CreateUserStepContainer$ConfirmPassword")).TypeText("passmenuqword!"); ie.Button(Find.ByName("ctl10$MainContentArea$ctl00$ctl00$CreateUserForm$__CustomNav0$StepNextButtonButton")).Click();
Figure: Simulating a user registration with WatiN
Selenium is a tool to create tests for web apps
Selenium’s output is a whole test class
Selenium’s output code is using relative URL’s (that you define in your test base URL)
WatiN: The code output from the test recorder v1 is quite complicated to read.
I prefer Seleniums: “selenium.Click” instead of the long string and then seeing the “Click()”
// WatiN watin.TextField(Find.ByName("ctl10$MainContentArea$ctl00$ctl00$CreateUserForm$CreateUserStepContainer$ConfirmPassword")).TypeText("password, f17"); watin.Button(Find.ByName("ctl10$MainContentArea$ctl00$ctl00$CreateUserForm$__CustomNav0$StepNextButtonButton")).Click(); // Selenium selenium.Type("ctl10_MainContentArea_ctl00_ctl00_CreateUserForm_CreateUserStepContainer_ConfirmPassword", "password"); selenium.Click("ctl10_MainContentArea_ctl00_ctl00_CreateUserForm___CustomNav0_StepNextButtonButton");
Figure: Code comparison of WatiN with Selenium. Enter text in a password field and click on button
WatiN : Output code from Watin Test recorder v1 was wrong.
Some input control TypeText() was missing
Finding of elements didn't always work E.g. <a href="xx"> <span> My funkty test </span> </a>
Running the tests
Selenium needs a JAVA server to execute the tests
WatiN doesn't need a proxy server!
Output from the Selenium Java server (see the 2 seconds of start up gap)
19:11:54.341 INFO - Command request: getNewBrowserSession[*chrome, http://REMOVED.ssw.com.au/Public/, ] on session null 19:11:54.341 INFO - creating new remote session 19:11:54.341 INFO - Allocated session 69581bdd207a4684b61f6c368af906f0 for http://REMOVED.ssw.com.au/Public/, launching... 19:11:54.370 INFO - Preparing Firefox profile... 19:11:56.895 INFO - Launching Firefox...
Code maintainance
Selenium makes working with Firefox perfectly together: uses the same name as in HTML
E.g. ctl10_MainContentArea_ctl00_ctl00_SubTotal
That means you can copy & paste from FireBug directly to Visual Studio
string priceSubTotalOnCheckout = selenium.GetText("ctl10_MainContentArea_ctl00_ctl00_SubTotal");
Watin replaces the underscores with a dollar sign (This is annoying when copy paste from FireBug)
ctl10_MainContentArea_ctl00_ctl00_SubTotal
needs to be converted to
ctl10$MainContentArea$ctl00$ctl00$SubTotal
string resultText = browser.Element(Find.ByName("ctl10$MainContentArea$ctl00$ctl00$SubTotal")).Text;
Note
Figure: Selenium is coming from the Java world, as you can see this here. No properties :-) --> GetXXX
What about Visual Studio 2010 and Test & Lab Manager
- In Test & Lab Manager you define a test case that links to a user story
- Now you run you test with an Action recording
- This is easy. Just follow the instructions from the test case
- Done
- Close down Test Lab Manager and open Visual Studio, add "Coded UI test" with an "Existing action recording"
- Code that you get
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.TestCase", "http://win-peterG:8080/tfs/DefaultCollection;Peter-Gfader-WebTest", "140", DataAccessMethod.Sequential), TestMethod] public void CodedUITestMethod1() { this.UIMap.Openbrowser(); this.UIMap.Gotostartpage();
this.UIMap.ClickonRegisterNew(); this.UIMap.EnterdetailsfirstnamelastnameemailpasswordParams.Ctl10MainContentAreaEditText = TestContext.DataRow["firstname"].ToString(); this.UIMap.EnterdetailsfirstnamelastnameemailpasswordParams.Ctl10MainContentAreaEdit1Text = TestContext.DataRow["lastname"].ToString(); this.UIMap.EnterdetailsfirstnamelastnameemailpasswordParams.Ctl10MainContentAreaEdit2Text1 = TestContext.DataRow["email"].ToString(); this.UIMap.EnterdetailsfirstnamelastnameemailpasswordParams.Ctl10MainContentAreaEdit3Text1 = TestContext.DataRow["email"].ToString(); this.UIMap.EnterdetailsfirstnamelastnameemailpasswordParams.Ctl10MainContentAreaEdit4Text = TestContext.DataRow["password"].ToString(); this.UIMap.EnterdetailsfirstnamelastnameemailpasswordParams.Ctl10MainContentAreaEdit5Text = TestContext.DataRow["password"].ToString(); this.UIMap.Enterdetailsfirstnamelastnameemailpassword(); this.UIMap.ClickonRegister();
this.UIMap.Searchforbag(); this.UIMap.Add1stbagfoundtoshoppingcart();
this.UIMap.Gotoshoppingcart();
this.UIMap.DoCheckout();
this.UIMap.EnterAddressdetails(); this.UIMap.Placeorder(); }
Figure: Code generated by VS2010 for a registration of a new user, searching for a bag, adding this bad and going through the checkout
VS2010 code is very easy to read. And there are a lot of things happening behind the scenes
UIMap is a huge file generated for you that does all the magic behind the scenes, like finding controls, clicking buttons, …
UIMap: Strongly typed representation of controls
How is Visual Studio finding controls?
public HtmlInputButton RegisterButton { get { if ((this.mRegisterButton == null)) { this.mRegisterButton = new HtmlInputButton(this); #region Search Criteria this.mRegisterButton.SearchProperties[HtmlProperties.Button.Id] = "ctl10_MainContentArea_ctl00_ctl00_CreateUserForm___CustomNav0_StepNextButtonButton"; this.mRegisterButton.SearchProperties[HtmlProperties.Button.Name] = "ctl10$MainContentArea$ctl00$ctl00$CreateUserForm$__CustomNav0$StepNextButtonButton"; this.mRegisterButton.FilterProperties[HtmlProperties.Button.DisplayText] = "Register"; this.mRegisterButton.FilterProperties[HtmlProperties.Button.Type] = "submit"; this.mRegisterButton.FilterProperties[HtmlProperties.Button.Title] = null; this.mRegisterButton.FilterProperties[HtmlProperties.Button.Class] = null; this.mRegisterButton.FilterProperties[HtmlProperties.Button.ControlDefinition] = "id=ctl10_MainContentArea_ctl00_ctl00_Cre"; this.mRegisterButton.FilterProperties[HtmlProperties.Button.TagInstance] = "40"; this.mRegisterButton.WindowTitles.Add("Peter Gfader | Sign Up - Windows Internet Explorer"); #endregion } return this.mRegisterButton; } }
Figure: VS 2010 Beta2 generated code for finding a button on a web page. I think this is way TOO STRICT
VS2010: All the "SearchProperties"above have to match, otherwise the button won’t be found. If too many controls are found from the "SearchProperties", the "FilterProperties" are applied one by one. All details on Balagans Blog - How does “Coded UI test” finds a control?
There is no option to customize the default generated SearchProperties
I would probably change that to
public HtmlInputButton RegisterButton { get { if ((this.mRegisterButton == null)) { this.mRegisterButton = new HtmlInputButton(this); #region Search Criteria this.mRegisterButton.FilterProperties[HtmlProperties.Button.DisplayText] = "Register"; this.mRegisterButton.FilterProperties[HtmlProperties.Button.Type] = "submit"; #endregion } return this.mRegisterButton; } }
Better way to search for the Register button. Filter on DisplayText and type of the control.
Note: This would fail if there are 2 buttons with "Register" and of type "Submit" on the page. Which is excellent!
Can VS2010 simulate a FireFox?
See this image for details about the VS2010 platform support
Figure: VS2010 platform support from http://videos.visitmix.com/MIX09/T83M
WebAII looks very promising. I will definitely have a closer look on that tool in the next weeks, months…
Conclusion: Please count the green ticks and red crosses
Other interesting opinions about Watin and Selenium on testdrivendeveloper
PERSONAL
I would not automate the UI too much because that makes your test very fragile for future changes. That you will have sooner or later!
BAD EXAMPLE
Create a coded UI test for a whole user interaction with your web app
e.g. Register, Login, Browse, Find, Add to Shopping cart, Update Billing Address, Update Shipping Address, Checkout, Pay, See Order successful
Makes your UI test very fragile!
But could be a “Done” criteria for your SCRUM team: "An acceptance UI test must be written for each user story"
GOOD EXAMPLE
1. Create a coded UI tests for single screens
e.g. Logon screen:
Assert "Username", "Password" boxes and "Login" button are there
2. Create a functional test for testing the actual Login functionality.
16 comments:
Hi,
nice comparison. Used Selenium in my last project and I love it for having fast UI tests. Especially when you're reusing/modifying UI user controls it's just great to ensure that the other pages still work fine (well, that's a test's purpose after all).
Another use of Selenium and its Firefox IDE is as a tool for filling out large forms during dev. Example: you work on a large form's (also wizard's) save functionality and you have to check whether the validators work correctly. So instead of filling out all the required fields each time you may just use Selenium, record it the first time and then replay as often as you wish. Really comfortable.
I started with Selenium the same way.
Automating my user creation process via the web.
I couldn't directly insert new users to the DB because it was dependent from a lot of tables.
So I had to use a Selenium extension at that time, to do the GOTO (a loop of 1 user creation)
I use watiN and it works just fine, but not with the recorder. Also, we all know recorder just makes thing a bit faster but in all cases you have to edit the code to make it work always.. like e.g. you cant register the same user twice so you need to have random values. It's better not to use the full id of a field in case it changes during edits and so many other examples
Hi Sherine
Do you have a blog where you share your experiences?
My experience was pretty similar to yours. But the Watin Recorder that I found rendered HTML so poorly that our site wasn't usable; it's probably using IE6. Looks like the Watin Recorder project is dead in the water.
Just a thought:
How can any automation tool help you find bug easier?? :O ->It can only help you find bugs that you thought might occur and will not help you find those bugs which of you haven't thought about.
Designing your automation is the key factor here.
Manual testing done by skilled test engineer is always helpful, no matter how much you have automated.
Hi Mohammad
#1
>>How can any automation tool help you find bug easier?
Cause writing/developing/recording tests puts you in the tester perspective and you see your software from a completely different point of view. This different view leads you to spot certain things and avoid certain things in the future.
#2
Agree!
Automation is the key!
Manual testing will always be needed! Automated tests can help, and it is not easy to find the balance...
Selenium looks great but I just want to make a comment on WatiN. We've been using WatiN in my current project with great success, we do not use any sort of recorder (and frankly, I've never missed it). We wrap all the html details in WatiN page objects so that we can easily change our GUI without breaking our workflows (which operate on the page objects, not the html details). Specflow + WatiN has been just smiles and laughter so far :-)
Hi Anonymous,
I use the recorder to get started with the tests, but then I refactor them out to have an abstraction of the controls. I guess similar as you do.
Record+Play is nice for demos but hard to maintain and cause brittle tests.
How long does it take on avg to execute 1 of your Specflow+WatiN tests?
Our (current) 417 specflow/watin tests ran last night for approx 1 hour and 30 mins (5233 seconds) at an average of 12,55 seconds pr test.
Hi Peter,
please help me on this case i used the selenium and it's great but now i need some recorder automation like selenium but working with silverlight and HTML5 and selenium doesn't working with.
awni.baggio@hotmail.com
Hi awni.baggio
Testing Silverlight is not supported by Selenium, because Selenium works on the HTML DOM level.
There is http://code.google.com/p/silverlight-selenium/ although I havent tried it yet
For testing Silverlight you might look into Telerik Test Studio http://www.telerik.com/automated-testing-tools.aspx
OR
Microsoft Visual Studio 2010 Feature Pack 2
There is also a video recording from Roy Osherove about Testing Silverlight
http://osherove.com/videos/2009/8/25/unit-testing-in-silverlight-silverunit-and-ms-sliverlight-te.html
Hi Guys, whatwould you suggest for wep applications running on IE?
>> wep applications running on IE
What do you mean by wep applications?
Hi Peter,
Very nice post on comparing these three Automation tools.
I would like to add a little in this.
>>Selenium needs a JAVA server to execute the tests
This is needed only when you use Selenium RC and every one now have started using Selenium WebDriver which doesn't require to have Java Server running. It was an old requirment for Selenium RC.
>>Selenium is quite slow to run
I think this is true agin in case of Selenium RC which can be fixed by using some workaround.
I wrote a little blog on "Why Selenium RC is so slow" which can be found at : http://www.anitpatel.net/2012/02/24/selenium-rc-why-selenium-rc-is-so-slow/
Thanks again for this cool post. Cheers.
-Anit Patel
Hi Anit
Thx for your additions.
I guess I need to update this entry a little.
Post a Comment