端到端测试工具

Nuxt 通过一起使用 AVA 和 jsdom 这两个 Node.js 模块,使得端到端测试变得非常容易和有趣。但是在为 Nuxt 应用程序中的测试实现和组合它们之前,让我们先深入了解这两个 Node.js 模块,看看它们是如何单独工作的,这样你就能对这些工具有一个扎实的基础理解。让我们从下一节的 jsdom 开始。

jsdom

简而言之,jsdom 是 W3C 文档对象模型 (DOM) 的基于 JavaScript 的 Node.js 实现。但是,这是什么意思?我们需要它做什么?想象一下,在 Node.js 应用程序(如 Express 和 Koa 应用程序)的服务器端,你需要操作原始 HTML 中的 DOM,但是服务器端没有 DOM,因此你无法做太多事情。这时 jsdom 就来帮助我们了。它将原始 HTML 转换为一个 DOM 片段,该片段在 Node.js 内部的工作方式类似于客户端的 DOM。然后,你可以使用像 jQuery 这样的客户端 JavaScript 库在 Node.js 上像操作客户端 DOM 一样轻松地操作 DOM。以下是服务器端应用程序的基本用法示例:

  1. 在服务器端应用程序上导入 jsdom:

    import jsdom from 'jsdom'
    const { JSDOM } = jsdom
  2. 将任何原始 HTML 字符串传递给 JSDOM 构造函数,你将获得一个 DOM 对象:

    const dom = new JSDOM('<!DOCTYPE html><p>Hello World</p>')
    console.log(dom.window.document.querySelector('p').textContent)

你从上面的代码片段中获得的 DOM 对象具有许多有用的属性,特别是 window 对象,然后你可以像在客户端一样开始操作你传入的 HTML 字符串。现在让我们将这个工具应用到你在上一章学到的 Koa API 上,该 API 可以在我们的 GitHub 仓库中的 /chapter-12/nuxt-universal/cross-domain/jwt/axios-module/backend/ 中找到,以打印 “Hello world” 消息。请按照以下步骤操作:

  1. 通过 npm 安装 jsdom 和 jQuery:

    $ npm i jsdom --save-dev
    $ npm i jquery --save-dev
  2. 导入 jsdom 并传递一个 HTML 字符串,就像我们在前面的基本用法示例中所做的那样:

    // src/modules/public/home/_routes/index.js
    import Router from 'koa-router'
    import jsdom from 'jsdom'
    const { JSDOM } = jsdom
    const router = new Router()
    const html = '<!DOCTYPE html><p>Hello World</p>'
    const dom = new JSDOM(html)
    const window = dom.window
    const text = window.document.querySelector('p').textContent
  3. 将文本输出到端点:

    router.get('/', async (ctx, next) => {
      ctx.type = 'json'
      ctx.body = {
        message: text
      }
    })

    当你在终端上运行 npm run dev 时,你应该在 localhost:4000/public 上看到 JSON 格式的 “Hello world” 消息(如下面的代码片段所示):

    {"status":200,"data":{"message":"Hello world"}}
  4. 在我们的 API 中创建一个电影模块,并使用 Axios 从 IMDb 网站获取一个 HTML 页面,将该 HTML 传递给 JSDOM 构造函数,导入 jQuery,然后将其应用于 jsdom 创建的 DOM window 对象,如下所示:

    // src/modules/public/movie/_routes/index.js
    const url = 'https://www.imdb.com/movies-in-theaters/'
    const { data } = await axios.get(url)
    const dom = new JSDOM(data)
    const $ = (require('jquery'))(dom.window)

    请注意,必须通过 npm 在你的项目目录中安装 Axios,你可以使用 npm i axios 来完成此操作。

  5. 将 jQuery 对象应用于所有具有 list_item 类的电影,并提取数据(每部电影的名称和放映时间),如下所示:

    var items = $('.list_item')
    var list = []
    $.each(items, function( key, item ) {
      var movieName = $('h4 a', item).text()
      var movieShowTime = $('h4 span', item).text()
      var movie = {
        name: movieName,
        showTime: movieShowTime
      }
      list.push(movie)
    })
  6. 将列表输出到端点:

    ctx.type = 'json'
    ctx.body = { list: list }

你将在 localhost:4000/public/movies 看到类似以下的电影列表(JSON 格式):

{"status": 200,"data": {"list": [{"name": " Onward (2020)","showTime": ""}, {"name": " Finding the Way Back (2020)","showTime": ""},......]}}

你可以在我们的 GitHub 仓库中的 /chapter-13/jsdom/ 找到这些示例。有关此 npm 包的更多信息,请访问 https://github.com/jsdom/jsdom。

你可以看到这个工具在服务器端是多么有用。它使我们能够像在客户端一样操作原始 HTML。现在让我们继续学习下一节的 AVA,并在我们的 Nuxt 应用程序中将其与 jsdom 一起使用之前,学习它的一些基本用法。

AVA

简而言之,AVA(不是 Ava 或 ava,发音为 /ˈeɪvə/)是 Node.js 的 JavaScript 测试运行器。市面上有很多测试运行器:Mocha、Jasmine 和 tape 等等。AVA 是现有列表的另一个替代方案。首先,AVA 很简单,非常容易设置。此外,它默认并行运行测试,这意味着你的测试将运行得很快。它适用于前端和后端 Javascript 应用程序。总而言之,它绝对值得一试。让我们按照以下步骤创建一个简单而基本的 Node.js 应用程序:

  1. 通过 npm 安装 AVA,并将其保存到 package.json 文件中的 devDependencies 选项:

    $ npm i ava --save-dev
  2. 安装 Babel 核心和其他 Babel 包,以便我们在应用程序的测试中编写 ES6 代码:

    $ npm i @babel/polyfill
    $ npm i @babel/core --save-dev
    $ npm i @babel/preset-env --save-dev
    $ npm i @babel/register --save-dev
  3. 在 package.json 文件中配置测试脚本,如下所示:

    // package.json
    {
      "scripts": {
        "test": "ava --verbose",
        "test:watch": "ava --watch"
      },
      "ava": {
        "require": [
          "./setup.js",
          "@babel/polyfill"
        ],
        "files": [
          "test/**/*"
        ]
      }
    }
  4. 在根目录下创建一个 setup.js 文件,其代码如下:

    // setup.js
    require('@babel/register')({
      babelrc: false,
      presets: ['@babel/preset-env']
    })
  5. 在我们的应用程序的这两个单独的文件中创建我们稍后要测试的以下类和函数:

    // src/hello.js
    export default class Greeter {
      static greet () {
        return 'hello world'
      }
    }
    
    // src/add.js
    export default function (num1, num2) {
      return num1 + num2
    }
  6. 在 /test/ 目录下创建一个 hello.js 测试文件,用于测试 /src/hello.js:

    // test/hello.js
    import test from 'ava'
    import hello from '../src/hello'
    test('should say hello world', t => {
      t.is('hello world', hello.greet())
    })
  7. 再次在 /test/ 目录下的另一个单独文件中创建一个测试,用于测试 /src/add.js:

    // test/add.js
    import test from 'ava'
    import add from '../src/add'
    test('amount should be 60', t => {
      t.is(add(10, 50), 60)
    })
  8. 在你的终端上运行所有测试:

    $ npm run test

    你也可以使用 --watch 标志运行测试以启用 AVA 的监视模式:

    $ npm run test:watch

    如果测试通过,你将得到以下结果:

    ✓ add › amount should be 60
    ✓ hello › should say hello world
    2 tests passed

    你可以在我们的 GitHub 仓库中的 /chapter-13/ava/ 找到上述示例。有关此 npm 包的更多信息,请访问 https://github.com/avajs/ava。

这很容易也很有趣,不是吗?看到我们的代码通过测试总是令人欣慰的。现在你已经对这个工具有了基本的了解,是时候在 Nuxt 应用程序中将其与 jsdom 一起实现了。让我们在下一节中开始吧。