Integration testing


    Integration testing is a logical extension of unit testing. In its simplest form, two units that have already been tested are combined into a component and the interface between them is tested.

    Integration testing


    The purpose of integration testing is to verify the functional, performance, and reliability between the modules that are integrated.

    Integration testing strategies


    1. Big-Bang Strategy

    2. Top Down Strategy

    3. Bottom Up Strategy

    4. Hybrid Strategy

    Big-Bang Strategy


    1. All components or modules are integrated simultaneously

    2. Individual modules are not integrated until all the modules are ready

    3. This approach is generally executed by those developers who follows the ‘Run it and see’ approach.

    4. Because of integrating everything at one time if any failures occurs then it become very difficult for the programmers to know the root cause of that failure.

    5. In case any bug arises then the developers has to detach the integrated modules in order to find the actual cause of the bug.

    Top Down Strategy


    Top Down Strategy


    1. Top-down integration testing is an integration testing technique used in order to simulate the behaviour of the lower-level modules that are not yet integrated

    2. Stubs are the modules that act as temporary replacement for a called module and give the same output as that of the actual product

    3. The replacement for the 'called' modules is known as 'Stubs' and is also used when the software needs to interact with an external system

    Bottom Up Strategy



    Each component at lower hierarchy is tested individually and then the components that rely upon these components are tested.

    Hybrid Strategy



    In Hybrid Integration Testing, we exploit the advantages of Top-down and Bottom-up approaches. As the name suggests, we make use of both the Integration techniques.

    Hybrid Strategy


    1. It is viewed as three layers; viz - The Main Target Layer, a layer above the target layer and a layer below the target layer.

    2. Testing is mainly focussed for the middle level target layer and is selected on the basis of system characteristics and the structure of the code.

    3. Hybrid Integration testing can be adopted if the customer wants to work on a working version of the application as soon as possible aimed at producing a basic working system in the earlier stages of the development cycle.

    Three Options for Top-Down Rails Testing


    1. Controller tests

    2. Integration tests

    3. Acceptance tests

    Controller tests


    1. also known as 'functional tests'

    2. also can be used as integration tests, especially as integration tests for backend

    3. provide some kind of end-to-end testing (controller params as input and http response code & name of rendered template as output)

    4. good for API integration tests

    Rails Integration test itself


    1. they’re able to simulate complex interactions utilizing more of the application stack

    2. they feed simulated HTTP requests to the Rails Dispatcher rather than through the controller

    3. integration tests don’t map directly to any specific source file

    4. from 5x to 10x slower, depending on test complexity

    Rails Integration test itself

    
    class ShopperInteractionsTest < ActionDispatch::IntegrationTest
      test "place order and check orders admin" do
        shopper = login_as users(:user)
        admin = login_as users(:administrator)
    
        product = products(:rails_book)
        shopper.post line_items_path, line_item: { product_id: product.id }
        shopper.follow_redirect!
        assert_equal root_path, shopper.path
    
        order_params = {
          name: "Chris Kottom",
          address: "My house",
          email: "chris@example.com",
          pay_type: "Credit Card"
        }
        assert_difference "Order.count" do
          shopper.post orders_path, order: order_params
        end
        shopper.follow_redirect!
        assert_equal root_path, shopper.path
    
        order = Order.last
        admin.get orders_path
        admin.assert_select "#orders #order_#{ order.id }" do
          admin.assert_select "a[href=?]", order_path(order.id)
        end
      end
    end
    					

    Acceptance Tests


    1. allows to tests the WHOLE application including frontend

    2. Tests are defined with a user-oriented API that mirrors the actions a user would perform

    3. includes script and stylesheet evaluation

    Capybara


    1. helps you test web applications by simulating how a real user would interact with your app

    2. Pluggable back-end drivers that give you several options ranging from simple (markup only) to the full-featured (full evaluation of Javascript and CSS styles)

    3. A slick, natural API that allows tests to be defined in language that mimics user interaction with the browser

    Capybara


    1. Management of multiple sessions

    2. Automatic following of redirect responses

    3. Ability to follow external URLs

    Capybara: Code Example

    
    RSpec.describe HomeController do
      describe "contact form" do
        before { visit '/' }
    
        context "with valid message" do
          it "sends the letter" do
            within("#section6") do
              fill_in "contact_message_name",    with: "Sergiy"
              fill_in "contact_message_email",   with: 'sergey.kukunin@gmail.com'
              select  "Just Saying Hi",           :from => "contact_message_subject"
              fill_in "contact_message_body",    with: "Glad to meet you"
            end
    
            expect { click_on "SEND" }.to change { ActionMailer::Base.deliveries.count }.by(1)
            expect(page).to have_content("Thank you for contacting us.")
          end
        end
      end
    
      describe "licenses" do
        it "shows all licenses" do
          visit licenses_path
    
          expect(page).to have_selector "table", count: 2
          expect(page).to have_selector "table:nth-child(1) tbody tr", count: 2
          expect(page).to have_selector "table:nth-child(1) thead", text: 'CA'
        end
      end
    end
    					

    Capybara: Setup

    1. install phantomjs

    2. In Gemfile
      
      gem 'capybara'
      gem 'poltergeist'
      						

    3. In rails_helper:
      								
      require 'capybara/poltergeist'
      require 'capybara/rspec'
      
      Capybara.javascript_driver = :poltergeist
      								
      							

    Capybara: CheatSheet


    Navigation


    
    visit('/projects')
    visit(post_comments_path(post))
    					






    More info: https://gist.github.com/zhengjia/428105

    Capybara: Clicking links and buttons


    
    click_link('id-of-link')
    click_link('Link Text')
    click_button('Save')
    click('Link Text') # Click either a link or a button
    click('Button Value')
    					

    Capybara: Interaction with forms


    
    fill_in('First Name', :with => 'John')
    fill_in('Password', :with => 'Seekrit')
    fill_in('Description', :with => 'Really Long Text…')
    choose('A Radio Button')
    check('A Checkbox')
    uncheck('A Checkbox')
    attach_file('Image', '/path/to/image.jpg')
    select('Option', :from => 'Select Box')
    					
    				

    Capybara: Scoping


    
    within("//li[@id='employee']") do
    	fill_in 'Name', :with => 'Jimmy'
    end
    
    within(:css, "li#employee") do
    	fill_in 'Name', :with => 'Jimmy'
    end
    
    within_fieldset('Employee') do
    	fill_in 'Name', :with => 'Jimmy'
    end
    
    within_table('Employee') do
    	fill_in 'Name', :with => 'Jimmy'
    end
    					

    Capybara: Querying


    
    page.has_xpath?('//table/tr')
    page.has_css?('table tr.foo')
    page.has_content?('foo')
    page.should have_xpath('//table/tr')
    page.should have_css('table tr.foo')
    page.should have_content('foo')
    page.should have_no_content('foo')
    find_field('First Name').value
    find_link('Hello').visible?
    find_button('Send').click
    find('//table/tr').click
    locate("//*[@id='overlay'").find("//h1").click
    all('a').each { |a| a[:href] }
    					

    Capybara: Scripting


    
    result = page.evaluate_script('4 + 4');
    					

    Capybara: Debugging


    
    save_and_open_page
    					

    Capybara: XPath and CSS


    
    within(:css, 'ul li') { ... }
    find(:css, 'ul li').text
    locate(:css, 'input#name').value
    
    Capybara.default_selector = :css
    within('ul li') { ... }
    find('ul li').text
    locate('input#name').value