In my experience the majority of automated testing for markup applications either uses HTTP requests and responses using a protocol library such as urllib or a browser-based automation library such as Selenium. Both approaches are useful and can be effective.
A web browser can be used as a simple way to quickly view the content returned for a given xHTML device. The browser will need an add-in to incorporate sufficient device headers to convince the web site that the request is from a particular mobile device. Similarly, WML can be rendered in Firefox by using another browser add-in. More information is available in the section titled “Utilities to help with testing browser applications.”
Let us start with an overview of how you can implement your first automated script for testing browser applications:
Consider adding code to detect failures, e.g., error messages that should not be in the responses. By detecting failures explicitly the tests will be more reliable (harder to fool) and errors can be handled sooner, rather than the test meekly waiting for the “expected result” until a timeout occurs.
The examples here are written in Python, a flexible programming language that is easy to experiment with interactively as well as being able to handle large-scale programs. Several other programming languages are able to provide similar capabilities, so try yours if you don't find Python suitable.
With four lines of Python, shown in Example 3.1, we are able to retrieve the contents of Google's mobile search homepage for the UK site. Note: the numbers of the bullet-points refer to the numbers in brackets from the preceding example Python code.
So with four simple lines of code we have the page content. We can also obtain more information, like the HTTP response headers by calling response.info()
And individual headers using response.info().typeheader
Here you may notice something strange: the content type indicates the content is in WML, rather than xHTML or HTML. Google's search engine seems to be defaulting to the oldest markup language, rather than the most popular one—why is that?
Early mobile wireless devices used WAP requests and expected WML responses. Later phones were often able to support both WML and xHTML, while newer phones support xHTML and HTML. Since the search engine does not have any indication of what markup language the requester wanted, it sends the earliest version. Google search is able to deliver the correct markup provided it receives sufficient “clues” in the HTTP request.
Two key HTTP headers generally provide enough information for the search engine to deliver appropriate content for a given device. By adding these headers we should be able to “fool” the search engine into returning the content it would return to the equivalent phone model. Let us go through these headers one by one:
The first header to consider is the “Accept” header. This is part of the HTTP standard and is used by the requester to tell the server what types of content it is able to use. For a desktop web browser the Accept header may be set to
This “accept” header tells the server the image file formats the browser can display, and then a catch-all for other content types, e.g., for text/html.
For a mobile browser that accepts xHTML, the Accept header will generally be set to:
As indicated with (1) in Example 3.4, in Python we can add this header using:
And using response.info().typeheader this time shows the response is in xHTML—phew!
At the time this example was created, September 2007, Google was promoting the “Google Maps” mobile application to users who had suitable phones. I wanted to write a simple test that checks whether the link is available on the xHTML homepage. As the link is only offered to users with suitable phone models, we need our test to pretend it is one of those phones. The User-Agent HTTP header is what we need to achieve this.
Here is an example of a user-agent string from a Nokia 6230 phone:
We can add this to our request by adding another header (shown in bold and indicated with (1) in Example 3.7:
Let us start by using a simple search to find out whether Google Maps is mentioned anywhere on the page.
If the string is not found content.find() returns -1.
So, a simple string search is enough to get us started, and here indicates that the string “Google Maps” is contained in the returned content. We could now write more involved “string searches,” e.g., to find and extract the URL for the download and make sure the page does not have multiple links to Google Maps, etc. However, Python offers a better approach using the very powerful regular-expression tools.
Four more lines of Python code are enough to perform the regular expression match and return the link to the download page.
Here are the four steps required:
We could easily refine this code to extract, and even download, the Google Maps software.
Both WML and xHTML return XML documents; therefore we can use XML processing techniques to locate content of interest. The following example demonstrates how to use standard xml Python modules to match a string or even a regular expression and return the link if it exists.
There is a powerful free Python module called Amara that can be used to address the xml structure using an intuitive dot addressing, e.g., html.body.div. Amara also supports XPATH expressions, e.g., //div[0].
Here is an example of using Amara to test whether the Google Maps link is available. The link is returned if Google Maps is found in the text of a link.
Example 3.12 is a little more involved, but still relatively easy to follow:
These sample Python scripts have demonstrated the various ways we can process xHTML content to:
We can build on these basic scripts to automate more of our mobile browser testing.
We can make the tests “data-driven” as follows:
Metadata facilitates our automated tests, e.g., user-agent strings, accept headers, etc. Data sources include:
Find ways to rate and weigh the data quality, as data is often incomplete, contradictory, or wrong. You may decide it's worth filtering and merging useful data into a common pool.
Once you have collected, filtered and merged your metadata it can be made available as a common source of data for your tests (and possibly also for your production systems). Figure 3.2 illustrates a single example of metadata for a Nokia 6230i device.
Do stuff with device data…
Carrier networks can sometimes affect the results returned, and sometimes even corrupt the content. If you have a suitable data connection (e.g., using a GPRS modem or a phone connected as a data modem) you should be able to run the tests over carrier networks and compare the responses returned over each carrier. Generally we expect all the responses to be identical (for the patterns and content we expect to receive). If differences occur, potentially, a given carrier's network/infrastructure has modified the content. The differences should then be investigated and assessed in terms of the impact they have on users.
Your test scripts should:
Note: One of the appendices includes information on how to configure a suitable data connection in Linux.
Networks and data plans vary and can affect the functioning of your applications. While you could test using an application on a phone, the problems may be hard to isolate from other issues related to the phone(s) you are using to test. A good way to isolate carrier and data plan issues is to run a custom test program on a computer with a wireless data modem, as Figure 3.3 shows.
One of the key frustrations of users for mobile wireless applications is how slow they are. Virtually all modern programming languages offer the ability to time how long things take to happen. If you start a timer just before making the HTTP request and stop it as soon as the HTTP response has been received, you will have a good idea of how long the OTA part of the transaction takes. If you choose to run similar tests for a range of carriers you can obtain a rough idea of the speed of each carrier for your local network conditions. Note: the speed varies significantly as local conditions change. Factors include:
Measuring the end-user experience is much more involved and outside the scope of the current material.
In our experience, certain patterns of xHTML cause problems for particular phone models. Sometimes the issue is size of the response, for others tags such as the bold tag cause the contents to be rendered poorly, some handsets have limitations on the image formats they can handle, one phone even makes the text larger when the tag specifies the font size should be small, etc.
The effect ranges from the page not being displayed at all to minor rendering issues.
We do not want our users to have a poor user-experience, so we want to ensure our content will not trigger issues on their phones. At one point we created individual tests to detect whether particular content was appropriate for a given model of phone. However, that work was time-consuming and did not scale well. Therefore we designed and implemented a rule-based engine that can query URLs while emulating a wide range of phone models. The responses are then checked using rules which detect any violation of the known issues for that model of phone.
We gather issues from a variety of sources, e.g., from bug reports, server logs, manual testing, etc; identify them (in terms of which devices are affected and when the issue occurs); quantify them (in terms of severity, impact, likelihood, etc.); and write rules to detect the issue.
We simulate the affected devices using a mobile device database (loosely based on WURFL, an open-source effort to collect mobile device characteristics). We make requests to a variety of web sites that should work for mobile devices and apply the rules to the response received. If a rule is broken the software reports an error, i.e., if the content would cause an issue for the emulated device.
Generally we are able to manually verify whether a bug really occurs by testing with a real phone. This helps us to remove false positives from our system.
Our developers are then able to modify the application software to prevent the issue from occurring. Their changes are generally also tested manually, e.g., for aesthetics and to ensure the content renders correctly on the affected devices.
Sometimes we are left with a number of open questions, such as:
One way to obtain the answers is to create a “Probe server” that interacts with devices to obtain the answers we need. The tests need to be unambiguous for the tester, particularly in terms of their ability to provide accurate answers. If the tester is confused on what the “correct” answer is then the tests are likely to take longer while the quality of the data may also be compromised. Also, try to reduce the time required for each test. I am aware of one commercial vendor that requires a tester to manually execute more than 1,000 distinct tests per device in order to identify the device's characteristics, which take several days to execute. I don't envy their testers!
Strengths:
Weaknesses:
One way to learn about the characteristics and issues for mobile phones is to use the phone to interact with a known set of web pages that contain various test cases, e.g., to determine which images are supported. If the web pages are interactive, then the user can provide feedback online while executing the tests (e.g., to confirm whether an image has been displayed correctly or not). The resulting data can then be codified into rules for that model of phone.
Furthermore, by running the rule-based checker against the test web pages the accuracy of the rule-based checker can be verified.
Large, sophisticated international web sites need to deliver content that is appropriate for each user. Factors that affect the selection of content include things like:
Sometimes we redirect an initial request to a more suitable user interface, e.g., from the general search to the mobile search, based on the capabilities of the device.
Automated tests can be used to test all aspects of these requirements to varying degrees of accuracy. For instance the device being used can be emulated quite easily using HTTP headers. Implementing support in our tests to process scripting support is significantly harder. If your tests need to process scripts, consider using third-party open-source libraries such as HtmlUnit.
Location can be inferred from data such as source IP address and other factors such as phone-specific HTTP headers.
User preferences are often stored in cookies and cookie content can be added relatively easily to HTTP requests. Some more sophisticated cookie strategies require more involved programming to mimic the behavior of the way a device handles them.
For xHTML, the content is sufficiently similar to HTML to allow us to use many of the generic automated test tools, provided the tools offer the ability to set and read the HTTP request and response headers.
HttpUnit and HtmlUnit enable Java developers familiar with the JUnit test framework to create similar tests as easily as using Python (except Java does not provide an interactive development capability). HtmlUnit is more capable and, as mentioned earlier, includes support for testing the JavaScript scripting language.
Various software tools and web sites provide the ability to test the “readiness” of a web site for mobile wireless devices. For instance, http://ready.mobi/launch.jsp?locale=en_EN allows a web site to be checked online in terms of readiness for mobile devices. There are other similar sites and services available; however, this one has more of a testing focus. It implements the w3c mobileOK basic tests http://www.w3.org/TR/mobileOK-basic10-tests/ and is able to simulate a variety of common handsets.
Browser add-ons such as: wmlbrowser, web developer, user agent switcher, and modify headers (all for Firefox) make manual testing significantly easier. All of these add-ons can be installed directly from Firefox from the tools menu. On Microsoft Windows the menu option is “Extensions” on Linux it is “Add-ons.”
XML tools, such as Oxygen (http://www.oxygenxml.com/), a commercial product, reduce the challenges of working with XML.
Firebug is a stunningly useful extension for Firefox that provides incredible analysis and debugging tools. Features range from displaying the XPATH of an element when the mouse is “hovered-over” page elements on an xHTML web page, to interactive debugging of JavaScript.
Another important tool for testing browser applications is a network traffic analyzer that helps decode the requests and responses actually sent between your machine and the server, rather than what you think or hope is being sent.