Writing Test Automation code traditionally has been a low-level activity. Find a window, find a control, set the value, click the button – and then – find the window, find the control, check the value, and so on. More often than not, a major portion of effort goes in what we call “Infrastructure” code than “Heartbeat” code.The core logic of the test is cluttered with plumbing to deal with the interaction with the application user-interface.
As a rule of thumb we have observed that in order to test X lines of code, it takes at least 2.5 X lines of code to test basic flow and about 4-5 X lines for reasonable coverage. Now given the scale of modern rich UI applications, the complexity of required tests can be anyone’s guess.
Many test automation attempts start with a straight translation of manual testing steps, interlaced with API calls to identify forms, fields, and other controls. This approach often produces quick results with few test cases getting automated in a very short period of time. However, like any other quick n dirty solutions, if not corrected at early stage results in reams of test-automation logic which is monolithic in structure and extremely fragile to maintain.So what can help us here?
In our daily life, we all use so many gadgets – laptops, cars, watches, refrigerators, etc, without ever worrying about the complexities of the underlying subsystems. Each of these devices provides specific features by combining many smaller sub-systems behind the scenes. This layering makes it easy to install a program on a laptop, adjust the time on a watch, make ice cubes in the refrigerator, and so on.
Similarly, while programming test automation if we write test logic in terms of high-level widgets instead of the underlying representations, it will make our tests a lot more readable and extremely amenable to change. After all,LoginForm.UserName = “UserName”
is a lot easier for brain cells to understand thanWindows.Application.Find(“My Application”).FindWindow(“LoginForm”).FindControl(“UserName”).SetValue(“UserName”)* *Not actual API, just representational
Another way to get this concept is to look at the concept of Zoom. Zoom lets us look at the same landscape at different levels of understanding. Each level of zoom will show entities relevant at that level.
Before even thinking of writing test flows, we should think of entities participating in these flows. Tests should be viewed as interactions between these entities rather than as sequential steps. This approach immediately adds up to ROI on the effort because it is easier to devise and test complex interactions between various entities than writing complex sequential scripts. This approach instantly shifts attention to tests over data by separating the two, data being input to interaction than being the primary test-driving factor.