TestCafe 搭建前端End-to-End自动化测试工具

What is Test Cafe

TestCafe is a node.js tool to automate end-to-end web testing, you can write tests in JS or TypeScript, run them and view results.
简言之, Testcafe就是一个可以自动化前端end-to-end测试的工具,我们可以使用简单的JS或者Typescript写测试用例。

Installation

preparation

需要提前安装NodeJS, 官网没有指定版本,本文基于NodeJS 8+撰写。

Install TestCafe

  1. Globally
    npm install -g testcafe
  2. Locally
    npm install --save-dev testcafe

建议使用本地安装,这样团队里其他人直接npm install便可安装相同版本的所有依赖。

How to run test cases

Command Line Interface

可以使用命令行执行单元测试

  1. 使用指定浏览器
    testcafe chrome tests.js
    testcafe path:/safari.app tests.js
  2. 使用所有安装的浏览器
    testcafe all tests.js
  3. headless mode
    Chrome 和 Firefox 支持 headless mode
    testcafe "chrome:headless" tests.js

更多信息请参考 Command Line Interface

Programming Interface

也可以写JS代码用Node执行单元测试,这也是本文着重推荐的方法,因为这个方式更加灵活。

  1. 引入工厂函数
    const createTestCafe = require('testcafe')
  2. 使用工厂函数获得TestCafe实例
    工厂函数接受三个参数, 分别是 host controlPanelPort servicePort,返回一个promise, 该promise的最终结果便是一个TestCafe实例

    createTestCafe('localhost', 1337, 1338)
    .then(testcafe => {
        /* ... */
    });

    TestCafe对外暴露三个方法,分别是: createBrowserConnection createRunner close,详情请参考 TestCafe Class

  3. 调用 createRunner
    testcafe.createRunner返回一个Runner实例,该实例对外暴露多个方法,用于配置和执行测试任务,支持链式调用,比如:

    const runner = testcafe.createRunner();
    return runner
        .src(['test1.js', 'test2.js']) // 可以提前定义一个数组,或者将需要执行的文件保存在一个文件里,更加灵活,也可以配置文件夹
        .filter((testName, fixtureName, fixturePath) => {
            //Add some filters based on testName, fixtureName, fixturePath
         })
         .browsers(["chrome:headless"])
         .reporter('json', stream) // stream is the report file, like const stream = fs.createWriteStream('report.json');
         .run({
             selectorTimeout: 10000, // the timeout testcafe wait for an element to appear
             skipJsErrors: true // to ignore JS error
         });

    详情请参考 Runner Class

How to write test cases

Code Structure

Fixture

TestCafe使用fixture来组织测试用例,一个测试文件必须包含一个或多个fixture

fixture(fixtureName)
fixture `fixtureName`

可以指定fixture的开始页面:

fixture.page(url)
fixture.page `url`

Test Case

然后写测试用例

test
    .page `url`
    (testName, async t=> {
        /* Test Code */
    })

注意传入的参数t,它是 test controller,包含测试API和测试用例上下文,使用它我们可以调用 test actions, 处理浏览器对话框,等待,执行断言。

Make Test Step Common

也许你会注意到 t 是在测试用例中拿到的, 如果我们需要把一个公用的action抽出来,如何获得 t 呢?
TestCafe提供了一种直接引入t的方式,此时t不包含具体测试用例的上下文,但包含了测试API, 比如:

async login() {
    await t
        .typeText("#user", "name")
        .typeText("#pwd", "pwd")
        .click("#login")
}

看到这里,也许你对typeText click很陌生,没关系,后面会提到。

Test Hooks

Test Hooks, 执行在Test Case之前或之后

fixture.beforeEach(fn(t))
fixture.afterEach(fn(t))
test.before(fn(t))
test.after(fn(t))

注意 test.before test.after会覆盖fixture.beforeEach fixture.afterEach, Test Hooks 同样会拿到Test Controller实例。

Skip Tests

可以跳过某些test case 或者fixture

fixture.skip
test.skip

也可以指定只执行某些test case或fixture

fixture.only
test.only

Selectors

请参考Selectors

Actions

请参考Actions

Assertions

AssertionDescription
eqldeep equal
notEqlnot deep equal
okactual is true
notOkactual is false
containsArray or String or Object or promise contains
notContainsArray or String or Object or promise not contains
typeOftype check
notTypeOftype check
gtGreater than
gtegreater than or equal to
ltless than
lteless than or equal to
withinrange from start and finish
notWithinnot range from start and finish
matchregex check
notMatchregex check

详情请参考Assertion API

Tricks

ClientFunction

在之前的章节我们说在 test case 中, 我们可以执行 test controller 对外暴露的 action, 执行断言,获取上下文变量等等,但是关于 client side 的数据却无法直接拿到,比如:

fixture("Fixture")
    test('window', async t=> {
        await t.navigateTo("url");
        await t.expect(window.location.href).eql("url")
    })

会报出如下错误:

window is not defined

TestCafe 提供了ClientFunction构造函数,我们可以传入一个回调函数,在回调函数中可以访问 window

const getWindowLocation = ClientFunction(() => window.location)
fixture("Fixture")
    test('window', async t=> {
        await t.navigateTo("url");
        let location = await getWindowLocation();
        await t.expect(location.href).eql("url")
    })

Role

在很多网站中,具有不同角色的用户可以访问不同的界面或功能,TestCafe 提供了Role构造方法并且在 TestController 中暴露 UseRole方法以便切换角色。

  1. 首先引入 Role 构造函数

    import { Role } from 'testcafe'
  2. 创建 role

    const user = Role(Env.LOGIN_URL, async t => {
        await t
            .typeText("userInput", "name")
            .typeText("pwdInput", "123")
            .click("submitBtn");
    });
  3. 在 test case 中切换 role

    t.useRole(user)

How to debug

笔者认为TestCafe的调试功能不太成熟,只支持下一步等简单操作

t.debug()
    原文作者:Sue1024
    原文地址: https://segmentfault.com/a/1190000016162968
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞