繁体   English   中英

设置测试数据以对单页Web应用程序及其后端进行全栈测试

[英]Setting up test data for full-stack testing of a single page web application and its back-end

我的问题的简短版本

在为Angular单页Web应用程序编写的Cucumber测试中,我如何完成通常在场景的“给定”部分中执行的任务(例如设置测试数据,定义数据库记录关联以及确保测试之间的数据库状态干净) )在测试全栈时,前端应用程序及其后端? 应用程序源代码存储在两个单独的Git存储库中,一个用于前端应用程序,一个用于后端。 后端是使用Rails API gem用Ruby编写的。 全栈测试该应用程序所面临的挑战来自这样一个事实,即它实际上是两个应用程序,而不是传统的Ruby on Rails应用程序未实现为单页应用程序。

我的问题的完整版本

我正在为Web应用程序编写一系列的Cucumber测试。 该应用程序由用Angular编写的前端单页应用程序和使用Rails API编写的后端API组成。 前端的源代码和后端的源代码分别位于各自的Git存储库中,从而在两个代码库之间提供了清晰的分隔。 此外,该应用程序使用MySQL和Elasticsearch。

过去,我在先前的Ruby on Rails项目中使用过Cucumber。 这些项目不是作为单页应用程序开发的。 在这些项目中,很容易在cumberber步骤定义中创建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 gems包含在项目中。 对我来说,这些工具包括:

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对象设置为测试数据并定义数据库记录关联的Factory Girl,以及用于确保测试之间的干净数据库状态的Database Cleaner。 使用JavaScript的Cucumber方案要求包含Selenium WebDriver。

对于我的单页应用程序,情况有所不同。 如上所述,该应用程序分为两个单独的代码库,一个用于Angular前端单页应用程序,另一个用于Rails API后端接口。

但是,像我的项目这样的单页应用程序仍然具有与不作为单页应用程序构建的更传统的Rails应用程序相同的测试要求。 有必要对应用程序进行全栈测试,以确保前端和后端的每个组件都能按预期工作。 在测试之前,需要定义黄瓜步骤以创建“给定的”前提,并且有必要确保测试之间的数据库干净。

如何使用Cucumber测试这样的应用程序(一个具有两个代码库的应用程序)实现为单页应用程序? 有一个适用于JavaScript的Cucumber版本,称为CucumberJS。 但是,我不知道如何使用CucumberJS创建固定装置,记录关联以及如何确保测试之间的干净数据库。 还有一个用于测试用Angular编写的JavaScript的工具,称为Protractor。 我想象该工具将取代Selenium WebDriver。

回答简短版本问题。

全栈测试该应用程序的挑战来自以下事实:它实际上是两个应用程序

您所描述的内容对单页应用程序来说是典型的。 我有很多spa示例(用E2E覆盖),其中后端是PHP,Dot.net或云Web服务(parse.com)中的RESTful API。 以我的观点,最好将此类应用程序视为2个不同的应用程序,并为每个应用程序编写2套不同的测试集。 我相信这是编写稳定,可扩展和快速的e2e测试的唯一方法。

基本上,我们要做的是创建一个本地的非持久性模拟API(使用javascript),专门用于测试。 以下是此类api的要求/指南列表:

  1. 提供测试服的模拟数据(已读取-结合测试服)
  2. 仅介绍使测试通过的足够方法。
  3. 它是非持久性的(请求参数是做出响应的全部,尽管可以有例外)。 所有持久性都在客户端上(本地存储,cookie)。 这很重要,因为只需清除客户端存储并刷新页面即可-您将获得应用程序的全新状态! 在测试整体的地方-您必须清除并重新填充数据库,这浪费时间并且完全不可扩展。
  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 / login请求实现一个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}));
  }
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM