Brief introduction
Automated integration testing is a very important part of Web applications, but because these test cases rely too much on specific Web page implementation details, this poses great challenges to authoring and maintenance. There are usually two ways to build a WEB application test case.
Manual scripting: Testers need to know what forms, input boxes, selection boxes, buttons, and so on on a Web page, and the names of these form elements, IDs, and so on, before they can use some tools to write test cases.
Build by tool Recording: For example, IBM Rational functional Tester provides the ability to automatically generate test cases by recording the user's actions on the Web interface.
Method 1 requires testers to know too much about Web page details, which makes it impossible for testers to focus on business logic and will have to spend a lot of time updating the script once the Web page changes. Method 2 automatically generates test scripts, but these scripts are poorly readable and can be difficult to maintain. Similarly, if a Web page changes, testers will need to record all of the scripts again.
So is there any way to overcome the above problems and make the work easier? The answer is YES!
For example, an online electronic bookstore, for users to buy the book scene, we can use the following script for integration testing:
Login ' test@test.com ', ' pass4you '/Login
List_books//List of books
Add_to_shop_cart ' Who says elephants can't dance '//Add to the cart the book who says elephants can't dance
Readers can see, "Login", "List_books", "add_to_shop_cart" These terms have completely separated from the specific page details, will not be affected by page changes, they are fully business-oriented, accurate embodiment of the application of the business logic, easy to understand, Easy to maintain and communicate with business people, and even business people can write test scripts themselves. There are so many advantages, then how to achieve them? This is the focus of this article: using dynamic language Ruby to implement a "business driven" WEB application test.
Ruby Introduction
Ruby, in Chinese, is Ruby, but in the computer field, it represents a fairly good object-oriented scripting language. It was born in 1993, and in recent years, with Ruby on Rails This "killer application" is rapidly growing in the field of Web development. Ruby was originally designed to absorb the essence of many other languages, such as the ability of the Perl language to handle text, the simplicity and readability of the Python language, as well as the ease of extensibility and powerful portability, the Smalltalk language's pure object-oriented grammar, This gives it the advantage of many other languages. Ruby's design philosophy is to minimize unnecessary trivial work in programming, and to allow programmers to enjoy programming while accomplishing their tasks.
Ruby features the following:
Object-oriented: In Ruby, everything is an object, including basic data types in other languages, such as integers.
In Java, for example, the absolute value of a number is Math.Abs (-20), but in Ruby everything is object,-20 is the object, so it can be done -20.abs, is it more image and intuitive?
Interpretive scripting language: No compilation, direct execution, short development cycle, easy debugging.
Dynamic: A class that has already been defined can be modified at run time.
The focus of this article is not to introduce the Ruby language itself, but interested readers can refer to the Reference Resources section.
Case analysis
51book
To show how to use Ruby for business-driven testing without getting readers into too much detail, this article assumes a simple online book application (51book), which supports the following main features:
1. Login: The user must log in to buy books.
Figure 1. Login
2. Browse Books: Include search for books by title.
Figure 2. Browse and search for books
3. Add the books to the shopping cart and see the "Add to Cart" link in Figure 2.
4. Change the number of books in the shopping cart and recalculate them.
Business operations
With the above introduction, the reader should have a simple understanding of 51book, then we consider how to conduct business-driven testing, first of all need to define business-oriented operations, so as to use them in test cases. For the sake of simplicity, we define the following business operations:
Table 1. Business operations
Domain-specific language (domain specific Language)
The so-called domain-specific language (domain specific LANGUAGE/DSL), its basic idea is "to ask for a special purpose", unlike the general-purpose language as the target scope covers all software problems, but specifically for a specific problem computer language. As its name claims, the language is not generic, but focused on a particular "domain", such as the SQL language is the DSL of the database, using SQL to complete a variety of data operations without concern for the underlying specific database implementations. Because of "domain-specific", it is not possible for you to use SQL to develop a desktop application.
The login, Add_to_shop_cart, and change_quantity we defined in the previous section is the DSL for the 51book online bookstore.
Martin Fowler the DSL into two broad categories: an external DSL and an internal DSL. For an external DSL, building what it needs to do is to: (1) Define a new domain-oriented syntax. (2) In a language to write an interpreter or compiler, because the language is new, we have a lot of work to do; then for the internal DSL, we can select a flexible language, select a subset of its syntax, and customize it using the dynamic nature of the language, This avoids the huge workload of creating a new language.
Ruby language is very rich in syntax and exceptionally flexible dynamic features that are ideal for creating dynamic DSLs. This article is about using Ruby to create a 51book test-oriented DSL.
Implementing business operations with Ruby DSL
Principle
Because Ruby is a dynamic scripting language that interprets execution, it provides a way to "evaluate" a piece of text. That is, we can provide a piece of text (not necessarily a complete program), and Ruby can execute it in a particular context, and of course the text needs to conform to Ruby's syntax.
For example, we have a file Bookshop.txt, which contains the following text: Login "Andy", "Pass4you", then how to execute it? First you need a context, and we can define a class to represent:
Listing 1. Bookshopdslbuilder
Class Bookshopdslbuilder
def self.execute (DSL)
builder=new
builder.instance_eval (File.read (DSL), DSL)
End
def login (user=nil,pwd=nil)
print user
print pwd
end
The code above is very simple, and you need to focus on static method Execute, what happens when you call Bookshop.txt as a parameter? Smart readers may have guessed that the values of user and PWD will be printed. This code shows two important features of the Ruby language:
The Instance_eval method executes a piece of text as code. The context of execution is the object bookshopdslbuilder. So when it touches the text "login", it automatically invokes the real method login.
When you call a method, you can do without parentheses. That's why Ruby will take the text login "Andy", "pass4you" as a reason for a method call.
These two features give us a "bridge" so that we can turn that business-oriented text such as "login", "Add_to_cart", "Search_book" into a call to a particular method. We can implement some logic in these methods.
Watir
We now have the ability to connect the scripts of business tests to Ruby's objects/methods, but a second bridge is needed to connect Ruby and Web applications so that the script-driven Web pages of business tests are tested. We want to have a software or tool that can drive browsers like people, such as clicking on links, filling out forms, clicking buttons, and so on. Of course, it can also check the results of the page, such as the expected text appears and so on.
Open Source Tool Watir is such a tool, in addition to the above features, it and the Ruby language can be seamless integration, and the browser, especially IE has a strong control capabilities. So we chose it as the second bridge.
Here's a simple example of using Watir, which goes to Google's home page, type "bookshop" in the search box, and then click the "Search" button. Watir fully inherits the simplicity of the Ruby language, and the reader can see that the script using Watir is fairly intuitive and fairly easy.
Listing 2. Watir Example
Require "watir"
ie = watir::ie.new
ie.goto "http://www.google.com"
Ie.text_field (: Name, "Q"). Set " Bookshop "
Ie.button (: Name," btng "). Click
Implement Login
With the above two "bridge", the concrete implementation is much simpler, for each business operation, we need to do is:
(1) Implementing a method with the same name in a Ruby object (Bookshopdslbuilder)
(2) using Watir to manipulate interface elements in the implementation of the method. Of course, the premise is that we need to know what elements are in the interface.
Let's take a look at the implementation of Login:
Listing 3. Login
Class Bookshopdslbuilder
include test::unit::assertions #include ruby unit assertion
def self.execute (DSL) C3/>builder=new
builder.instance_eval (File.read (DSL), DSL)
builder
End
def initialize
@login _url = ' http://localhost:3000/bookshop/login ' #51Book entrance
#creat a ie instance
@ie = Watir::ie.new # Create a Watir instance end
def login (user=nil,pwd=nil)
@ie. Goto @login_url
@ie. Text_field (: ID, "User_ Name "). Set (user) # sets the username
@ie. Text_field (: ID," User_password "). Set (PWD) # Sets the password
@ie. Button (: Type, "Submit"). Click the submit button End
Implement Add_to_shop_cart
This is a relatively complex operation in a shopping cart that is added to a book, because it receives a caption for a book, while "Add to Cart" on the interface is a link that contains only the books ID and does not contain a caption, so it cannot be positioned directly.
Listing 4. Add to Cart
<table width= ' 100% ' class= ' book ' >
<tr>
<td>title:</td>
<td>agile Development</td> # title here
</tr>
<tr>
<td>description:</td>
<td >the Book of Agile development</td>
</tr>
<tr>
<td>price:</td>
<td>30.0</td>
</tr>
<tr>
<td colspan= "2" > #Add_To_Cart Link is here
<a href= '/bookshop/add_to_cart/1 ' >add to cart</a>
</td>
</tr>
</ Table>
In this case, you can take advantage of Watir's strong support for XPath, find the title first, find the link from the title, and then click the link.
Listing 5. Using XPath
def add_to_cart (title)
table = @ie. Table (: XPath,
"//table[@class = ' book ']/tbody/tr/td[text () = ' +title+ ']/ .. /.. /.. /")
if Table[1][2].text = = Title
href = table[4][1].links[1].href
@ie. Link (: href,href). Click
End End
For other business operations, the specific implementation is similar, here no longer introduced, interested readers can see the code in the attachment, and finally we look at a business-oriented Web page Test example:
Listing 6. A complete example
Login ' Andy ', ' pass4you '
add_to_cart ' Agile development '
add_to_cart ' savor Blue '
add_to_cart ' Programming Ruby '
change_quantity ' Agile development ',
change_quantity ' Savor Blue ',
Change_ Quantity ' programming Ruby ',
recalculate_cart
assert_total_price_is 900 search_book
' Ant Cookbook '
Add_to_cart ' Ant Cookbook '
assert_total_price_is 910
Summarize
So far, we've implemented a "business-driven" WEB application test through Ruby, and we've actually implemented a business-oriented abstraction layer through Ruby, using Watir to map business operations to Html pages. This way, when the Html page changes, only the mapping needs to be adjusted without changing the operations of the business layer. And because they are fully business-oriented, developers or testers can concentrate on testing the business logic without getting bogged down in the details of the implementation.
After mastering this method, readers can apply to their own programs, can make their own test writing simple, easy to understand, easy to maintain. will provide a great deal of test efficiency for WEB applications.