Request spec in Action

    Testing has become an integral part of any software product development, whether it is an application for a desktop computer, mobile device or web. Already no one denies the importance of this stage and the consequences that its absence will bring. Among them, a lot of time to check each element (page), and unexpected surprises in the behavior of the product, an increase in the cost of fixing the program. The principle of writing tests is quite simple - “yellow”, “red”, “green”, refactoring. Where yellow is the pending test, red is the failed test, and green is the system working as it should.

    For each type of programming, there are many types of testing. But there are common points that are present everywhere. Since the main kind of my work is creating web applications under ROR, let's talk about the features of testing these applications.

    Environment setup

    You can find many test environments (Test Unit, Rspec, Cucumber & etc), but I personally actively use Rspec. It allows you to give the tests a beautiful look, but at the same time maintain the look of the code. We’ll add a new group to the gemfile: you may be surprised and ask: “Why add rspec to development mode?” Everything is quite simple - rspec adds the appropriate specs when generating model, controller, scaffold. After installing gem, let's run the last installation command:

    group :development, :test do
    gem "rspec-rails", ">= 2.5"

    rails g rspec:install

    Now we can run our tests with the rake rspec command. The negative side of this approach is that at the slightest change in our project, we will again and again have to execute this command, which will pull through absolutely all the tests. It follows that it is necessary to find some watcher so that it executes the necessary commands instead of us. At the moment I know about two good solutions - autotest and guard. Autotest came to rails from other frameworks, having proved itself well, and earlier I used only it. But recently, I met with a lovely solution in the form of a guard. The guard itself does not carry the necessary functionality, but when you use it with add-ons, it turns out a very gorgeous thing. The guard has about 2 dozen of these additions, and they carry enormous opportunities. However, let us dwell on one thing - guard-rspec. Install the necessary files:

    group :test do
    gem ‘guard-rspec’

    We execute the initialization command: The first will create a guardfile (observer configuration file), the second will add rspec-specific actions. Now, on the guard command, you have watcher working, ready at any time to draw up the necessary spec. But the log for this solution is quite boring, so add a little color to it. First, install the notification libraries. And here we are faced with the first problems - you and your partner have different OS (Mac OS and Linux), but everyone needs to test. The solution for us was the following solution: Next, we replace all the points in rspec with a percentage calculus: And finally, in the Guardfile we write the following: Run the tests. In the console, we get a beautiful progress bar, and when the test finishes, a pop-up window appears.

    guard init .
    guard init rspec

    gem 'libnotify' , :require => false if RUBY_PLATFORM =~ /linux/i
    gem 'rb-inotify', :require => false if RUBY_PLATFORM =~ /linux/i
    gem 'rb-fsevent', :require => false if RUBY_PLATFORM =~ /darwin/i

    gem 'fuubar'

    guard 'rspec', :cli =>'--format Fuubar --color'

    The next step for setting up a testing environment is to make our tests clean. After all, no one wants us to come across values ​​and records in the database from previous checks when performing tests. A good choice in this case might be gem database_cleaner. Its configuration is shown below: After setting up the cleaner, it's nice to talk about creating testable content. Rspec suggests using mock, but personally, I prefer to generate real objects. You can use machinist or factory_girl to create various objects. I am not particularly familiar with machinist, so I can’t say anything about him. But I’ve been working with factory_girl for a long time, and gem has never raised any complaints. Add our gems to the test group:

    config.before(:suite) do
    DatabaseCleaner.strategy = :truncation

    config.before(:each) do

    config.after(:each) do

    group :test do
    gem ‘guard_rspec’
    gem ‘factory_girl_rails’
    gem ‘database_cleaner’

    The rest of the use I suggest to consider outside this article at the link

    Testing itself

    Having established a basic testing environment, you can talk about its features. Rspec divides all testing in parts, that is, copies of the folders in the app section are created in the spec folder. During my modest period of development and testing, I only found the models, helpers, mailers sections useful. And then the question arises: "What to do with the most important components of controllers and views?" In my opinion, the solution that rspec offers is not entirely complete, and it creates a not very real situation. Therefore, for my development, I chose to test requests and received responses. To do this, install capybara. The author of the library (Jonas Nicklas) describes it like this:

    “Capybara aims to simplify the process of integration testing Rack applications, such as Rails, Sinatra or Merb. Capybara simulate show a real user would interact with a web application. ”

    Which literally sounds like:

    “ Capybara guinea pig simplifies the process of complex testing, simulating user behavior in your application”

    Add it to the gemfile. After you need to add Capybara libraries in the file spec / test_helper.rb:

    require 'capybara/rspec'

    Now our tests are filled with many functional and convenient testing methods and manipulating a virtual page. Let's start in order:

    A visit to the page is done in the clear visit method:

    visit ‘/’

    In addition to lowercase addresses, the method accepts rails path helper:

    visit car_wheels_path(car)

    But the main functionality of the library is the accessible page object. This object is a virtual page for testing. To get its contents, you just need to turn to the body method:

    puts page.body

    Let's go through the list of manipulation commands. Text and password fields are filled with the fill_in method, which takes the first parameter as the id, class, name of the element, and the with parameter sets the content: To select an option, select uses the select method (thanks, Kep), which first takes a value and then the element for manipulation : select 'Silver',: from => 'car [color]' There are also check, uncheck, choose methods whose purpose is to change the state of the checkbox and radio button. They accept only the identifier of the element:

    fill_in ‘car_manufacture’, :with=>’Audi’
    fill_in ‘car[model]’, :with=>’A4’

    check ‘car[full_package]’
    choose ‘car[year][2010]’

    But it happens that in the page there are several elements with the same name, or, God forbid, id. To do this, there is a within block method that restricts the search inside the specified element: To click buttons and links, there are several methods - universal (click_on) and specific (click_link, click_button): Now let's move on to checking the resulting structure. To check for the presence of a DOM element, the have_selector method is present: But what if you need to check the number of these elements? That's all simple enough - we add the count parameter: In situations where the element itself is not fazhn, and it is important only the page.have_content method is useful?

    within ‘form#payment_card’ do
    #много манипуляций

    click_on ‘submit_form’
    click_link ‘read_more’

    page.should have_selector('table tr')

    page.should have_selector(‘table tr’, :count=>3)

    page.should have_content(“Audi club”)

    But what about js?

    Having written a couple of specs, you already noticed that capybara completely ignores js scripts. The developers took this step due to the preservation of performance when passing the tests. When there is a need to check our page with full functionality, we use the js spec parameter:

    it ‘should have many js’, :js=>true do
    visit …

    A window of your favorite browser will appear before us, the tested page will open, and the cursor will do all the movements. Just magic, but let's figure it out. Actually capybara just switched the web driver to process the test page. By default, the rack driver is used, which operates only on the content received with the response. When using the js parameter, capybara begins to handle the selenium driver. Selenium launches a system browser, unless otherwise specified, and performs all desired actions. Everything is good and beautiful, except for a couple of points. Firstly, the test run time becomes very long. And not surprisingly, in addition to loading the rails environment itself, the test launches the browser, plus the manipulations also take some time. Secondly, I was not happy with the constant display of the browser. Therefore, I had to abandon selenium in favor of an alternative web driver - capybara-webkit. This gem was specially written to solve these problems. To install the library, in addition to capybara-webkit itself, you need to install another qt library. After spec_helper we specify which driver to use for pages with javascript:

    Capybara.javascript_driver :webkit

    Now capybara will perform integrated tests quickly and without unnecessary animation.

    Another interesting point that you come across will be checking the elements that are loaded using ajax. The have_selector and have_content methods do not always work, so we use methods such as all, find, first: Also, the find and first methods can be useful for emulating clicks on elements other than buttons and links. If you wanted to execute some kind of script, then capybara will come in handy here: Initially, this seems like complete nonsense - "Well, what's the point of running js tests?" And the answer will be a situation where you need to trace the behavior of the page to actions other than click and select: This is how we emulated the hover over a paragraph of the cursor.

    first(‘’).should be

    all(‘’).should have(3).items


    page.execute_javascript “alert(‘Hello world’)”

    page.execute_javascript ‘$(“p.long_text”).hover();’

    A couple of observations from life

    And at the end of my post a couple of tips from personal experience. When using capybara, database_cleaner and factory_girl with any js web driver, the created resources will not be displayed on the test page. To correct this situation, the following setting:

    config.use_transactional_fixtures = false

    Another interesting trick is the focus in rspec, the effectiveness of which is undeniable in resource-intensive tests. Focus adjustment is as follows. First, add the lines to the configuration file of the testing environment: After, to perform the actions of interest, it will be enough to add a parameter named: focus => true and the list of specs will be filtered.

    config.filter_run :focus=>true
    config.run_all_when_everything_filtered = true

    useful links

    Capybara Webkit
    Data base cleaner
    Factory girl rails

    Also popular now: