Tutorial on implementing simple thing-Driven web applications using Ruby, rubyweb
Introduction
For Web applications, automated integration testing is a very important part. However, because these test cases are too dependent on the implementation details of specific Web pages, this poses a great challenge to writing and maintenance. Generally, there are two ways to generate Web application test cases.
Manual script writing: testers need to know which forms, input boxes, selection boxes, buttons, and other attributes of these form elements on the Web page, as well as the names and IDs of these form elements, then some tools can be used to compile test cases.
Recording generation using tools: for example, IBM Rational Functional Tester provides the ability to automatically generate test cases by recording user operations on the Web interface.
Method 1 requires the tester to know too much about the Web page details, which makes it impossible for the tester to focus on the business logic. Once the Web page changes, it will have to spend a lot of energy to update the script. Method 2 can automatically generate test scripts, but these scripts are poorly readable, making maintenance difficult. Similarly, if the Web page changes, the tester also needs to record all the scripts.
Is there any way to overcome the above problems and make work easier? The answer is yes!
For example, in an online e-bookstore, we can use the following scripts for integration testing for user book purchasing scenarios:
Login 'test @ test.com ', 'pass4you' // log on
List_books // list books
Add_to_shop_cart 'Who says the elephant cannot dance' // Add the book "Who says the elephant cannot dance" to the shopping cart
Readers can see that the terms "login", "list_books", "add_to_shop_cart" are completely different from the specific page details and will not be affected by page changes, they are completely business-oriented, accurately reflecting the application's business logic, easy to understand, easy to maintain, and can also communicate with business personnel, and even business personnel can write test scripts themselves. With so many advantages, how can we implement them? This is the focus of this article: using the dynamic language Ruby to implement "business-driven" Web application testing.
Ruby Introduction
Ruby indicates Ruby in Chinese, but in the computer field, it represents a very good object-oriented scripting language. It was born in 1993. In recent years, with Ruby on Rails, the "Killer application" has become increasingly popular in the Web development field. Ruby was initially designed to absorb the essence of many other languages, such as the text processing capabilities of perl, the simplicity and readability of Python, as well as convenient scalability and powerful portability capabilities, the pure object-oriented Syntax of Smalltalk gives it the advantages of many other languages. Ruby's design philosophy is to minimize unnecessary trivial work during programming, so that programmers can fully enjoy programming while completing tasks.
Ruby has the following features:
Object-oriented: In Ruby, everything is an object, including basic data types in other languages, such as integers.
For example, in Java, Math is used to calculate the absolute value of a number. abs (-20), but in Ruby everything is an object,-20 is also an object, so it is possible to do this-define abs, isn't it more visual and intuitive?
Interpreted scripting language: requires no compilation, direct execution, short development cycle, and convenient debugging.
Dynamic: defined classes can be modified at runtime.
This article does not focus on the Ruby language. If you are interested, refer to the reference resources section.
Case Analysis
51 book
To demonstrate how to use Ruby for business-driven testing without getting readers into too many details, this article assumes a simple online book purchase application (51 book for short ), this application supports the following functions:
1. Logon: You must log on to purchase books.
Figure 1. Logon
2. Browse books: including searching books by title.
Figure 2. Browse and search books
3. Add the books to the shopping cart. See the "Add to cart" link in Figure 2.
4. Change the number of books in the shopping cart and recalculate them.
Business Operations
Through the above introduction, the reader should have a simple understanding of 51 books. Next we will consider how to conduct business-driven testing. First, we need to define business-oriented operations, in this way, they can be used in test cases. For simplicity, we define the following business operations:
Table 1. Business Operations
Domain Specific Language)
The basic idea of domain specific language/DSL is "not seeking for specialization", which does not cover all software problems as the general target language does, it is a computer language dedicated to a specific problem. As its name claims, this language is not universal, but focuses on a specific "domain". For example, SQL is the database DSL, you can use SQL to perform various data operations without having to worry about the specific underlying database implementation. It is impossible for you to use SQL to develop a desktop application.
The login, add_to_shop_cart, and change_quantity defined in the previous section are DSL for 51 book online bookstores.
Martin Fowler divides DSL into two categories: External DSL and internal DSL. For external DSL, what needs to be done to build it is: (1) define a new domain-oriented syntax. (2) Compile the interpreter or compiler in a certain language. Because the language is brand new, we have a lot of work to do. For internal DSL, we can select a flexible language, select a subset of its syntax, and use the dynamic features of the language for customization, thus avoiding the huge workload of recreating a new language.
The Ruby language has rich syntax and flexible dynamic characteristics, and is suitable for creating dynamic DSL. This article uses Ruby to create a tested DSL for 51 books.
Use Ruby DSL for business operations
Principle
Ruby is a dynamic scripting language that implements interpretation. It provides a method for executing "evaluate" a piece of text. That is to say, we can provide a piece of text (not a complete program), and Ruby can execute it in a specific context. Of course, this text must comply with the Ruby syntax.
For example, we have a file bookshop.txt that contains the following text: login "andy", "pass4you". How can we execute it? First, we need a context. We can define a class to represent it:
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 end
The above code is very simple. You need to pay attention to the static method execute. What happens when bookshop.txt is called as a parameter? Smart readers may have guessed that the user and pwd values will be printed out. This Code demonstrates two important features of the Ruby language:
The instance_eval method executes a piece of text as code. The execution context is the BookshopDSLBuilder object. Therefore, when it encounters the text "login", it will automatically call the real method login.
When calling a method, you can leave no brackets. This is why Ruby regards the text login "andy" and "pass4you" as a method call.
These two features provide us with a "bridge", so that we can take the text for business testing, such as "login" and "add_to_cart ", "search_book" and so on are converted to calls to specific methods. We can implement some logic in these methods.
Watir
Now we have been able to connect the scripts for business testing with Ruby objects/methods, but we still need the second bridge to connect Ruby and Web applications, in this way, the Business Test script can drive the Web page for testing. We hope to have a software or tool that can drive browser operations like a person, such as clicking a link, filling a form, and clicking a button. Of course, it can also check the page results, such as whether the expected text appears.
Watir is an open-source tool. In addition to the above features, Watir can be seamlessly integrated with the Ruby language and has powerful control capabilities for browsers, especially IE. So we chose it as the second bridge.
The following is a simple example of using watir. It enters the Google homepage, type "bookshop" in the search box, and then click "Search. Watir fully inherits the simple and clear features of the Ruby language. You can see that the script using Watir is quite intuitive and 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 bridges, the specific implementation is much simpler. What we need to do for each business operation is:
(1) implement a method with the same name in a Ruby object (BookshopDSLBuilder)
(2) In method implementation, watir is used to operate interface elements. The premise is that we need to know the elements on the interface.
Let's take a look at the implementation of Login:
Listing 3. Login
Class BookshopDSLBuilder include Test: Unit: Assertions # include the Assertion def self.exe cute (dsl) builder of ruby unit = new builder. instance_eval (File. read (dsl), dsl) builder end def initialize @ login_url = 'HTTP: // localhost: 3000/bookshop/login' #51 Book entry # 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) # set the username @ ie. text_field (: id, "user_password "). set (pwd) # set the password @ ie. button (: type, "submit "). click # click the submit button end
Implement add_to_shop_cart
This operation is relatively complicated in the shopping Cart of a book, because the parameter it receives is the title of a book, while "Add to Cart" on the interface is a book id, the link does not contain the title, so it cannot be directly located.
Listing 4. Add to Cart
<Table width = '000000' class = 'book'> <tr> <td> title: </td> <td> Agile development </td> # The title is here </tr> <td> description: </td> <td> The book of agile development </td> </tr> <td> price: </td> <td> 30.0 </td> </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, Watir can be used to provide strong support for xpath. First, locate the title, find the link from the title, and then click the link.
Listing 5. Use 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 methods are similar. Here we will not introduce them one by one. Interested readers can refer to the Code in the attachment. Finally, let's take 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',10 change_quantity 'Savor Blue',10 change_quantity 'Programming Ruby',10 recalculate_cart assert_total_price_is 900 search_book 'Ant cookbook' add_to_cart 'Ant cookbook' assert_total_price_is 910
Summary
So far, we have achieved "business-driven" Web application testing through Ruby. In fact, we have implemented a business-oriented abstraction layer through Ruby, watir is used to map business operations to operations on Html pages. In this way, when the Html page changes, you only need to adjust the ing without changing the operations at the business layer. At the same time, because they are completely business-oriented, developers or testers can focus on testing the business logic without getting into implementation details.
After you have mastered this method, you can apply it to your own program, which makes your testing and writing simple, easy to understand, and easy to maintain. This will greatly improve the testing efficiency of Web applications.