Design Pattern in use - Implementing UI Test Application Using WatiN
Many developers either know or have heard about design patterns and knowingly or unknowingly are using them to solve the famous programming scenarios like Singleton Connection String or 3th party control adaptors. But in the software specific tasks which are different case by case, I always observe, using design patterns is being forgotten or ignored which lead to have a really complicated code to maintain.
It seems, quite often we are using Design-Patterns just in the implementation of core classes and frameworks. Whereas design pattern should be ubiquitous in all layers like Business Layer, as well as core.
Task Title: Implementing an application to test UI of a live web application using WatiN framework.
Scenario for testing:
In our scenario there are 3 different web pages. Login.aspx, Default.aspx and SecondPage.aspx.
First of all each user should login to the application and then the application will redirect him to the Default.aspx. On the opened page, the user is able to do some functionalities like opening a hyperlink. Obviously without logging to the application the user would not be able to go further and consequently the test case flow should be stopped.
Also, on the default page user should be able to open the “SecondPage.aspx” by clicking on a hyperlink. If under any circumstances the “SecondPage” can not be opened this step will be failed and our testing flow is going to be terminated.
Let’s find a proper Design Pattern:
We have different web pages and some activities and functionalities on each of them. This represents a flow of tasks which are occurring one after another and step by step.
As you can see in the above picture, we need to start our flow, if there is something wrong we will go to the End of process. In login state the application should try to login to the web application, under any circumstances that user will not be able to login to the web application the Test process should be terminated and go to the End. Which Design Pattern is really close to do this task? I choose Chain of Responsibility.
You can see three projects inside the solution:
1- PortalTestApp: Sample web application is playing the role of your live web application.
2- UITestingFlow: All base classes and infrastructure about UI testing framework have been located inside this project.
3- WatinUITest: A simple console application to run and test the final result. you can replace this project with UnitTest, Desktop or windows service applications.
Look through the UITestingFlow project and see these classes:
ITestProcess: Each state of our flow should implement this interface for doing it’s own task.
TestWorkflowHandler: This class is the heart of Chain of Responsibility design pattern and maintains all the steps of flow. Actually this class will run all the steps, one by another based on the order of states, as we asked at the initialization phase.
BaseState: I have created a base class to put some common functionalities of each state inside in(like logging data to a database or exception handling and etc..). All state inherited from this base class. This is exactly Template design pattern.
States Folder: As you can see in this folder, for each state I have created one simple class which is inherited from BaseState and implement ITestProcess.
It is the usage of our framework to test the UI:
StartTesting startClass = new StartTesting();
TestWorkflowHandler startState = new TestWorkflowHandler(startClass);
TestWorkflowHandler logingState = new TestWorkflowHandler(new Login());
TestWorkflowHandler OpenSecondPage = new TestWorkflowHandler(new OpenSecondPage());
TestWorkflowHandler end = new TestWorkflowHandler(new EndTesting()); // Defining Test Flow
OpenSecondPage.RegisterNextStep(end); // Start Test Flow
As you can see in the above code, TestWorkflowHandler is playing the role
of a wrapper for each state, it enables states to contain the next step inside.
So at the end of doing job, each state knows what is the next step to be executed.
For logging the result of each state I wrote in console window which is really easy to replace by a database or other sources.
Benefits of using design pattern in this task:
By implementing this task using Chain Of Responsibility design pattern, we have totally different classes for each state which lead to having a separate and clean business rules for each step. Testing and maintaining this code is much more easier than other types of coding and also, easily we can add a new flow state to the current flow.
I recommend to add a new web page in the web application project and a new step in testing flow to understand how it is going to be easy to expand and change this infrastructure.
Finally, I want to draw your attention to this important notice that, when you are working on a task, just try to explain and clean up the whole activities and jobs, and do all your best to find the closest design pattern to your need. Needless to say that, in many cases you need to mix more than one design pattern to overcome your job.