2015-06-14 44 views
1

短,我的問題的版本:設置測試數據單頁web應用的全棧測試,其後端

在一個角單個頁面的Web應用程序的書面黃瓜測試,我該怎麼辦完成通常在場景的「給定」部分執行的任務(例如設置測試數據,定義數據庫記錄關聯以及在測試之間確保數據庫之間的乾淨狀態),測試整個堆棧時,前端應用程序和它的後端?應用程序源代碼存儲在兩個獨立的Git存儲庫中,一個用於前端應用程序,另一個用於後端。後端是使用Rails API gem以Ruby編寫的。測試這個應用程序全棧的挑戰來自這樣一個事實,即它實際上是兩個應用程序,與更傳統的Ruby on Rails應用程序沒有作爲一個單獨的頁面應用程序實現相反。

我的問題的完整版

我期待編寫Web應用程序的一系列黃瓜測試。該應用程序由一個用Angular編寫的前端單頁應用程序和一個使用Rails API編寫的後端API組成。前端的源代碼和後端的源代碼都存放在他們自己的Git倉庫中,在兩個代碼庫之間提供了一個乾淨的分隔。此外,該應用程序使用MySQL和Elasticsearch。

我以前在以前的Ruby on Rails項目中使用過Cucumber。這些項目不是作爲單頁面應用程序開發的。在這些項目中,很容易在Cucumber步驟定義中創建Ruby對象作爲測試數據。例如,考慮從Rails項目,這不是一個單一的網頁應用以下特點文件:

# features/home_page.feature 
Feature: Home page 

    Scenario: Viewing application's home page 
    Given there's a post titled "My first" with "Hello, BDD world!" content 
    When I am on the homepage 
    Then I should see the "My first" post 

在此功能文件的步驟可以通過以下幾個步驟定義來實現:

# features/step_definitions/home_page_steps.rb 
Given(/^there's a post titled "(.*?)" with "(.*?)" content$/) do |title, content| 
    @post = FactoryGirl.create(:post, title: title, content: content) 
end 

When(/^I am on the homepage$/) do 
    visit root_path 
end 

Then(/^I should see the "(.*?)" post$/) do |title| 
    @post = Post.find_by_title(title) 

    page.should have_content(@post.title)summary of the question 
    page.should have_content(@post.content) 
end 

在Ruby on Rails項目不是作爲單頁面應用程序開發的,測試工具可以作爲Ruby寶石包含在項目中。對我來說,這些工具將包括:

group :test do 
    gem 'shoulda-matchers' 
    gem 'cucumber-rails', require: false 
    gem 'database_cleaner' 
    gem 'selenium-webdriver' 
end 

group :development, :test do 
    gem 'factory_girl_rails' 
end 

,你可以看到,這包括工廠女孩,用於建立Ruby對象的測試數據和定義數據庫記錄協會和數據庫清理,用來保證一個乾淨的數據庫狀態在測試之間。包含Selenium WebDriver對於使用JavaScript的Cucumber場景是必需的。

我的單頁應用程序的情況不同。如上所述,應用程序分爲兩個獨立的代碼庫,一個用於Angular前端單頁面應用程序,另一個用於Rails API後端界面。

但是,像我的項目這樣的單頁應用程序仍然具有與更傳統的Rails應用程序沒有構建爲單頁應用程序相同的測試需求。有必要測試應用程序全堆棧以確保每個組件(前端和後端)按預期一起工作。將需要定義黃瓜步驟,在測試之前創建「給定」前提條件,並且有必要確保測試之間有一個乾淨的數據庫。

如何使用Cucumber測試這樣的應用程序,其中包含兩個代碼庫,作爲單頁應用程序實現?有一個用於JavaScript的Cucumber版本叫做CucumberJS。但是,我不知道如何創建燈具,記錄關聯,並確保使用CucumberJS進行測試之間的乾淨數據庫。還有一個用於測試用Angular編寫的稱爲量角器的JavaScript的工具。我想象這個工具代替了Selenium WebDriver。

回答

0

回答的短版的問題。

在測試這個應用程序的全堆棧的挑戰來自於一個事實,即它實際上是兩個應用程序

你描述的是tipical單頁的應用程序。我有許多spa例子(覆蓋E2E),其中後端是PHP,Dot.net中的RESTful API或任何雲網絡服務(parse.com)。以我的觀點來看,最好將這些應用程序作爲2個不同的應用程序,併爲每個應用程序編寫2組不同的測試。我相信這是編寫穩定,可擴展且快速的e2e測試的唯一方法。

基本上我們要做的是創建一個本地非持久模擬api(在JavaScript中),尤其是測試。下面是對這樣的API的要求/準則列表:

  1. 提供的測試套裝模擬數據(讀 - 它被加上測試服)
  2. 佔地面積剛夠方法,使測試通過。
  3. 它是不存在的(請求參數就是做出響應的全部,儘管可能有例外)。所有的持久性都在客戶端(localstorage,cookies)上。這很重要,因爲只需清除客戶端存儲並刷新頁面 - 即可獲得應用程序的全新狀態!在哪裏測試一個巨無霸 - 你必須清理和重新填充數據庫,這是一個浪費時間和完全不可擴展的過程。
  4. 嵌入到角庫中,它是測試套裝和開發過程的一部分。

這在實踐中看起來如何。 比方說,我們正在測試的網站的登錄功能,它有3個場景:

var homepage = require('pages/homepage'); //page object for home page 

describe('Authentication', function() { 

    beforeEach(function() { 
    browser.manage().deleteAllCookies(); //clear persistance 
    browser.refresh(); //refresh page 
    homepage.get(); //go to homepage 
    }); 

    it('should show error when user enters wrong credentials', function() { 
    homepage.signIn('admin', '123'); //submit invalid credentials 
    expect(browser.getCurrentUrl()).toMatch('/home$');  
    expect(homepage.getSignInForm()).toContain('wrong credentials'); 
    }); 

}); 

爲了滿足這些測試,我們所要做的就是實現對POST /登錄請求的API:

router.get('/login', function (req, res) { 
    var username = req.body.username, password = req.body.password; 

    if (password !== 'admin') { 
    res.status(404).json({"error": "wrong credentials"}); 
    } else { 
    res.json(User(username})); 
    } 
});