Archive for the ‘Testing’ Category
Multipage validator
If you need a quick overview whether the internal links of your website are working and the markup is valid, checkout the Multipage Validator tool.
Popularity: 1% [?]
New version of CI output formatter available
With Cucumber 0.4 the API for the output formatters has been changed. We updated our output formatter according to these changes. It is now compatible with Cucumber versions 0.4.x to 0.6.x.
The the updated code can be found here: imedo_ci_formatter.rb
Popularity: 1% [?]
Matching elements on complex web pages with Webrat 2
In the first part of this article it was shown how to use CSS selectors for matching elements on complex web pages. But selectors are not the only way of matching HTML elements, Webrat also supports matching via XPath.
XPath matchers can be combined with CSS-selector matchers. This is really useful if not, for example, the content of an element should be matched but the element itself like in the following example. Here a form is used to display data as default value in its input elements. This can be the case in web applications in which data should be edited easily without additional clicks.
<div id="content">
<form>
Label 1: <input id="entry_1" name="entry[1]" value="Entry 1"/>
Label 2: <input id="entry_2" name="entry[2]" value="Entry 2"/>
<input type="submit">
</form>
</div>
Matching the default values of input elements with Webrat can look like the following lines of code. It is a nested combination of CSS-selector and XPath matching in order to have a readable error message if the actual output differs from the expected.
response.body.should have_selector("#content") do |content|
content.should have_tag("form") do |form|
form.should have_selector("#entry_1") do |input|
input.should have_xpath("@value") do |value|
value.should contain("Entry 1")
end
end
end
end
XPath matchers are currently not support by Webrat’s within() method and therefore cannot be used to limit the area on a web page where an action should take place, e.g. clicking of a link. They can only be used for evaluating the response of an action.
Popularity: 1% [?]
Matching elements on complex web pages with Webrat
Writing feature, integration, or acceptance tests with Webrat is a lot easier with simple web pages than it is with huge pages which provide much content. It can get really annoying to find the correct links or buttons to click. The same applies for matching content elements on complex pages in order to evaluate whether a test case was successful or not, since the same content can appear on different areas of one web page. Both issues can escalate if the position of layout elements is variable like in A/B usability tests or if a front-end layout manager is used. CSS selectors can help to find a layout element on a web page independent of its position. In this article is demonstrated how CSS selectors can be used with Webrat.
Given
In order to present the usage of CSS selectors with Webrat the following example is used. It shows a layout element called “content” which contains a table with two rows and each row provides the same options for its entry: Edit and delete.
<div id="content">
<table>
<thead>
<tr><th>Name</th><th>Options</th></tr>
</thead>
<tbody>
<tr id="entry_1" class="odd">
<td>Entry 1</td>
<td><a href="">Edit</a> <a href="">Delete</a></td>
</tr>
<tr id="entry_2" class="even">
<td>Entry 2</td>
<td><a href="">Edit</a> <a href="">Delete</a></td>
</tr>
</tbody>
</table>
</div>
When
In order to find the corresponding delete link for one particular entry in the example, it is necessary to define a scope in which the link can be found. With Webrat this can be achieved with the within() method.
within "#entry_2" do |scope| scope.click_link "Delete" end
Within() does only support the following selectors which have been defined in W3C CSS level 1.
- Type selectors, e.g. “table”
- Class selectors, e.g. “tr.odd”
- ID selectors, e.g. “#content”
The nesting of within() calls is currently not supported which means that well chosen IDs in the HTML code are necessary for good tests.
Then
In order to evaluate the response of the example after clicking the delete link of the second entry, the following statement would be sufficient, but in case the test did not work as expected it would return an error message which includes the content of the whole web page.
response.body.should_not contain("Entry 2")
Narrowing the part of the HTML code to the CSS selector which should be evaluated helps to get a more readable error message, since it only includes the selected part. In opposite to the the within() method have_selector() and have_tag() can be used nested, too. If a selector, e.g. in case of an error, is not available on a web page, an error message for the current scope is generated. This could be the whole page if the selector was the first one. Therefore it is recommended to start with a selector which is available even if an error occurs.
response.body.should have_selector("#content") do |content|
content.should have_tag("tbody") do |table|
table.should_not contain("Entry 2")
end
end
Using selectors in order to match elements on a web page has the disadvantage of a bigger dependency to the HTML code. Changing the name of a CSS selector can break test case. But this disadvantage should be insignificant compared to the achievement of error messages in which the actual problem is easily identifiable.
UPDATE: Due to a bug in Webrat should_not() does currently not work in a have_selector() block. The bug ticket contains a workaround for this issue.
Popularity: 1% [?]
Writing good stories
One of the biggest problems in software development has nothing to do with coding. It is about communication, the “code monkey versus software artist problem”.
Business people tend to specify as much as possible, but often lack the necessary knowledge of the technical details. From their point of view software developers are code monkeys who are supposed to implement specifications. On the other side programmers often see themselves as software artists who need total freedom since they are the ones who know the code.
The truth lies – like in most cases – somewhere in between. Feature requests are a result of business decisions which are made in the e.g. marketing or sales departments and usually need to be realized as soon as possible. But only software developers can estimate the needed resources to implement these features. They know which particular tasks have to be done, since they know the code.
One process which currently seems to be the solution for bringing business and software development together is agile software development with Scrum. It uses the rules of extreme programming (XP) and is therefore lightweight with low specification overhead and short release cycles. But still some specification needs to be done. Although the user stories of XP are really short they can contain quite a bit on information if they follow certain rules. Here are six rules which can help to get more information from one story. These rules do not conflict with the advices for writing stories in XP, but can be seen as a more practical approach which is based on them.
1 One use case per story
The first rule is to limit one story to one use case, i.e. only one use case for one feature is added or altered. For example if a new feature called “simple web forum” with the following use cases needs to be implemented.
- Guest views forum entry
- User writes forum entry
- User edits forum entry
- Moderator deletes forum entry
Each of these use case should be developed as one single story.
2 Consistent story format
Rule number two is to use a consistent format for the stories. The feature description part of the language Gherkin used by Cucumber is a good way of keeping stories short, but readable. In the following example is shown how it can be used to describe a use case.
Use Case: User writes forum entry
In order to produce user-generated content for one topic
As a logged in user
I want to write a new forum entry
One use case description consists of four lines. The first line is a short summary of the use case. Line number two, the “in order to” line, is reserved for a brief business value explanation. And the last two lines are supposed to describe the uses case itself: Who needs to do what.
3 Cover all wanted scenarios with a story
Rule number three is about the used semantic. A story should always be formulated as generic as possible so that it covers all wanted scenarios. This is because giving only a specific scenario like in the following bad example means that only this scenario should be implemented.
Bad example:
Use Case: Little Red Riding Hood searches for "Wolf"
In order to see how the Big Bad Wolf looks like
As Little Red Riding Hood
I want to search for "Wolf"
Good example:
Use Case: Guest searches for keyword
In order to get information about a keyword
As a guest
I want to search for a keyword
4 Use of scenarios to describe use case
Sometimes the expected behavior for a scenario of a use case is different than for others, e.g. if access control is an issue. In this case the possible scenarios should be described in the story as well. Here, the scenario syntax of Gherkin can be used.
Use Case: User searches for content
In order to get information about a keyword
As a user
I want to search for a keyword
Scenario: User searches for private content
Given a user Big Bad Wolf
And a user named Little Red Riding Hood
And Big Bad Wolf's private document with information about the Big Bad Wolf
When Little Red Riding Hood searches for "Wolf"
Then Little Red Riding Hood should not see the document about the Big Bad Wolf
5 Roles need to be known to the system
The fifth rule is that a role in a use case description of a story should always be known to the system, otherwise it is supposed to be added to the system. Like in the examples of rule 3 and 4 the Little Red Riding Hood might be a user name, but is probably no defined role. But e.g. the role “guest” stands for an unregistered visitor.
6 Use acceptance criteria for additional specification
In order to define additional things for one story it should be possible to give acceptance criteria for the QA team. This is rule number six. Acceptance criteria should be short and in list form. For the example with the keyword search one could be the following.
- A search form should be on every page
Popularity: 1% [?]
File uploads with webrat in Ruby on Rails 2.0.2
Webrat supports file upload in web forms with the method attach_file. Due to a lack of multipart form support for integration tests in Action Pack 2.0.2, this does not work with Rails 2.0.2.
It has been added in version 2.1., but for those who are still using 2.0.2, with the following code you can upgrade the particular part of Action Pack to 2.1. Just add it to your tests so that it overwrites the loaded Action Pack code.
CI output formatter update for Cucumber 0.3.9x
In the 0.3.9x releases of Cucumber the output generation has been changed in a way which prevents our output formatter from marking scenarios with undefined steps as pending.
Here’s the updated code: imedo_ci_formatter.rb
Popularity: 1% [?]
Testing PDF generation
Generating PDFs in a Rails application is a fairly common task. Maybe you want to create a letter, report, document or maybe an invoice. Either way the stuff that normally ends up in an PDF is important and you want to make sure the right stuff ends up there.
This pretty much sounds like a case for automated testing. But how do you test PDF content? One option would be to generate the PDF and then create a HTML out of the PDF using pdftohtml, parse the HTML and make some assertions. As you can guess, this approach isn’t very feasable, because the generated HTML isn’t very easy to parse.
Most of the time PDF generation in Rails applications is done using the RTex Plugin – the PDF is generated via LaTeX. This makes testing a lot easier because you can just parse and check the generated LaTeX-Source.
Everyone how has seen a LaTeX source file may ask: How the hell do I parse that?
In our case we added some “helper” comments like ”% SUM BEGIN” and ”% SUM END” before and after the part we were interested in and then used basic RegEx to parse out the interesting part. You have to manually check that the markup still looks as expected due to the newline handling of LaTeX (one is ok, two = new paragraph). Most of the time it is sufficient to look for ERB-Tags and use < %- instead of < %.
This approach works pretty well for us. One question which you should always keep in mind when you write tests is: What do I test on this level of testing and what do I leave out.
For the PDF/LaTeX-Testcase we choose to test the basic interaction between the objects that provide values for the PDF generation and the Template. We don’t test all combinations, just a few basic cases. Testing all or at least a lot of combinations, edge cases etc. is clearly a concern of unit tests.
Popularity: 1% [?]
Perl error “No space left on device” on Hudson slaves
Some of our tests are using a locally installed version of the W3C markup validator in order to check the generated pages. This worked well when running the tests manually, but as soon as we started the tests on one of our Hudson CI slaves some tests failed with the following message.
open3: close(main::SPIN) failed: No space left on device at /usr/lib/cgi-bin/chec
Of course there was plenty of disk space on the slave left. The message was raised by the Perl script of the validator, so it might not only be a W3C validator related issue, but a problem with calling a Perl CGI script from inside a Hudson job.
However, we fixed this problem by upgrading the Java version on our CI slaves from Sun Java 1.5 to 1.6.
Popularity: 1% [?]
Hudson dashboard for feedback monitor
In order to have a better overview over the build status of our projects we changed the dashboard’s stylesheet for our Hudson build monitor. The following image shows an example dashboard using our stylesheet.

And here is our CSS code written by tkadauke.
#header,
#viewList,
#side-panel { display: none; }
#projectstatus tr:first-child { display:none }
#projectstatus tr { float:left; width: 15em; height:3em; overflow: hidden }
#projectstatus tr > td { display: block; float:left; width:10em; height:3em }
#projectstatus tr td[data] {display:none}
#projectstatus tr td[data="0"],
#projectstatus tr td[data="4"],
#projectstatus tr td[data="6"],
#projectstatus tr td[data="8"] {display:block; width: 3em}
#projectstatus tr td.healthReport { display:none }
#projectstatus tr td a img { display:none }
You can use the Stylish add-on for Firefox to inject it into the Hudson dashbord.
Popularity: 1% [?]
