临时文档存放处,如果想围观我的话请移步到本人独立博客——http://besteric.com

WATiN/R Testing Design Pattern

上一篇 / 下一篇  2009-09-15 15:06:04 / 个人分类:蛋疼的自动化

转载于:http://consultingblogs.emc.com/richardgriffin/archive/2006/11/14/Testing-Design-Pattern-for-using-WATiR_2F00_N.aspx

如果打不开,草,自己看着办

Do you want your tests fixtures to look like this ?

 

        [TestMethod]
       publicvoidEnterInvalidUsernameAndPassword()
       {
           //Navigate to home page
           
IEinstance =HomePageManager.NavigatetoHomePage();           

           //Check that there are no items in the basket
           
if(!BasketManager.ValidateBasketIsEmpty(instance))
           {
               //if not clear it
               
BasketManager.ClearBasketItems(instance);
           

           //Sign out of the session
           
SignInManager.SignOut(instance);          

           //Attempt a signin with invalid user name
           
SignInManager.SignIn(instance,"test&tester.com","fake",true);           

           //make sure that the oops message is visible and the text is correct
           
Assert.IsTrue(instance.ContainsText("Oops! You made a mistake!"));

           Assert.IsTrue(instance.ContainsText("Please enter a valid email address."));
       }

 

In this post I will provide a outline for an approach you can use to refactor your tests and create a more maintainable and flexible design to use in your WATiR/N tests.

 

TheWATiR WebRecorder++and theWATiN WebRecorder++are great tools that help create test scripts quickly. In the short term they provide the ability to create lightweight test scripts by both the developer and the tester. The recorders output code so that the user becomes familiar with seeing the language and becomes used to certain constructs in that language. Once the test script. has been recorded, verification code is written in the form. ofassertsto ensure that the required level of functionality is being delivered. Based on these factors, the creation oftest fixturesusing WATiR/N is a two-stage process consisting ofrecordingandverifyingactivities.


With a complex or enterprise web site, thetest fixturestarts to get rather large, rather quickly, bringing with it management and maintainability issues. When creating tests using this particular approach there are some problems; a large amount of copying and pasting happens astest fixturesstart to overlap; resulting in duplicate code for testing components that are reused across the site on different pages; and the navigational code for requesting pages in the site is consistently the same. One way around this is to provide a template that contains the default actions that yourtest fixturerequires, record the test and crank out the verification code, copy this and add the code to the template and stash this away. A simple and effective way to improve productivity as the main parts of the test are predefined and heavily tested so if youtest scriptbarfs due to coding errors they are isolated to the new code that has been added to the template, allowing you to isolate the issue and quickly fix the problem.


The template helps but does not really solve the problems mentioned above. As a programmer we understand that low coupling and high levels of cohesion helps to make the code base easier to manage and maintain. Therefore, why not apply these principles to thetest suite. Therefore, I created a design that would increase cohesion and remove and need to copy and paste code, Don’t Repeat Yourself (DRY). To implement such a design, there needs to be a separation of concerns, by breaking awaydata,processing logicandtest fixture. At this point it is important note that changes to HTML element id’s can cause yourtest fixtureto break, and there is a question of responsibility over thetests. One of the reason that prompted the refactoring of the tests was based on observations that the developers were not owning the tests. So the tester spent more time maintaining existing tests rather than creating new tests scripts. For the moment it is best that we assume all parties are responsible.


Earlier I identified the three areas to be refactored,data,processing logicand thetests scriptsthat we want to rinse. Here I am going to classify the id’s and names of HTML elements as thedatapart of the puzzle. Each page on the site needs to be mirrored to create a test data object, the data objects are simple property bags containing the id and names of the HTML elements located on the page. By creating this design, it tackles the issues around cohesion mentioned earlier. Having all the names and id’s of elements on the page in one place means that, when there is change on the page updating the variables happens in one place. The result, of the refactoring means that for each page on the web site there is a corresponding property bag class that contains the id’s of HTML elements and a property to access that HTML element.


The simple base structure, contains an abstract class Abstract Pagethat implements an interfaceIPage. The interface provides the ability to access either a secure or an unsecure web page. All other data classes that are created are derived from theAbstractPageclass and therefore all data classes that are created retain the ability to have a secure and unsecure url’s. To adding a new interface or extending the existingIPageinterface you will be able to add the extra functionality you require. The design is about containment and isolation, to allow for the auto generation of implemented pages and page components. The secure and unsecureUrlproperties are populated from a configuration file so that you can point the test scripts at a particular server with ease. A future enhancement that I would like to introduce is the ability for data classes to be auto generated using a CodeSmith template.


So now that we have meet thedataaspect of the design, we can move on to the reusablelogical processingactions of the design. The functionality that is exposed or expected to be exposed is presented via a manager of the component or page. Therefore, in the current design there is a manager that you speak with to perform. an action. The manager uses the data objects to access the HTML elements on the page to perform. the task at hand requested. The processing logic is contained within the manager objects, it is here where you define common tasks on a page or component. Once there is duplication or common functionality requirements then this is the place where the code should live.


 

There is a one to one mapping between the managers and the page or control. Therefore there is a 1 to 1 mapping between themanagerand thedataclass, you will notice that each implementation of themanagerclass are sealed so that they can’t be extended, they are closed. The next noticeable facet is that each of the managers are thread safe singletons. The managers are created from common code or duplicate code found in the outputted code of the recorder. Such action tasks as,“Login a user with the correct username and password”or a simple action,“navigate to homepage”make up the logical processing. These actions are common and are very reusable, achieving the goal of cohesion and enforcing the separation of concerns that we want from the pattern. They can also be made into your own toolset of controls that after a time provide a comprehensive framework. For instance most web sites that provide a mechanism to order products or service require a login and will have a shopping basket to order and pay for goods. By adding reusable basket testing components to your framework will help you become more productive.


        [TestMethod]
       publicvoidEnterInvalidUsernameAndPassword()
       {
           //Navigate to home page
           IEinstance =HomePageManager.NavigatetoHomePage();           

           //Check that there are no items in the basket
           
if(!BasketManager.ValidateBasketIsEmpty(instance))
           {
               //if not clear it
               
BasketManager.ClearBasketItems(instance);
           

           //Sign out of the session
           
SignInManager.SignOut(instance);           

           //Attempt a signin with invalid user name
           
SignInManager.SignIn(instance,"test&tester.com","fake",true);           

           //make sure that the oops message is visible and the text is correct
           
Assert.IsTrue(instance.ContainsText("Oops! You made a mistake!"));
           Assert.IsTrue(instance.ContainsText("Please enter a valid email address."));
       }


The final piece of the puzzle are thetestfixturesWhen using the recorder mechanism it can be easy to hit a curve where the QA person is spending more time doing maintenance tasks rather than creatingtestfixturesfor the site. Thesetest scriptsthat are produced can be confusing and prone to error caused by copy and pasting code from other areas of the test suite. To provide a solution to this the QA can now write there tests in a more English notation that can be easily read and understood, by a BA or developer. How is this achieved? This is done through the using interactions with themanagersof thepageand or themanagersof component areas of the site to create atest scriptfor a particular area of the system. Allowing the QA / tester / developer to concentrate more on the creation of the test rather than the maintaining of the test. By designing layers of abstractiontest fixturescan build high level readable tests.

 

The article has covered a mechanism for creating an abstract test design pattern based on using recorders that are commonly available to the development and testing teams. The ability of implementing an abstract design delivers a large amount of reusable code base that can be used on different projects that you work on, and could even be used as benchmarks for new projects starting up that have a similar level of functionality.


TAG:

 

评分:0

我来说两句

Open Toolbar