2015-06-14 45 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})); 
    } 
});