Skip to content

测试

AdonisJS 内置支持编写测试。您无需安装额外的包或配置应用程序以准备测试 - 所有繁重的工作都已完成。

您可以使用以下 ace 命令运行应用程序测试。

sh
node ace test

测试存储在 tests 目录中,我们进一步按类型组织测试。例如,功能测试存储在 tests/functional 目录中,单元测试存储在 tests/unit 目录中。

功能测试是指由外向内的测试,您将对应用程序发出真实的 HTTP 请求来测试给定流程或端点的功能。例如,您可能有一组用于创建用户的功能测试。

一些社区可能将功能测试称为特性测试或端到端测试。AdonisJS 对您如何称呼它们很灵活。我们决定使用功能测试这个术语。

配置测试运行器

AdonisJS 使用 Japa 来编写和运行测试。因此,我们建议阅读 Japa 文档以更好地了解其 API 和配置选项。

测试套件

测试套件在 adonisrc.ts 文件中定义。默认情况下,我们注册了 functionalunit 测试套件。如果需要,您可以删除现有套件并从头开始。

ts
{
  tests: {
    suites: [
      {
        name: 'functional',
        files: ['tests/functional/**/*.spec.(js|ts)']
      },
      {
        name: 'unit',
        files: ['tests/unit/**/*.spec.(js|ts)']
      }
    ]
  }
}
  • 套件结合了套件的唯一名称和文件的 glob 模式。
  • 当您运行特定套件的测试时,只会导入与该套件相关的文件。

您可以使用 tests/bootstrap.ts 文件中定义的 configureSuite 钩子在运行时配置套件。例如,运行功能测试时,您可以注册套件级别的钩子来启动 HTTP 服务器。

ts
export const configureSuite: Config['configureSuite'] = (suite) => {
  if (['browser', 'functional', 'e2e'].includes(suite.name)) {
    return suite.setup(() => testUtils.httpServer().start())
  }
}

运行器钩子

运行器钩子是您可以在所有测试之前和之后运行的全局操作。钩子使用 tests/boostrap.ts 文件中的 runnerHooks 属性定义。

ts
export const runnerHooks: Required<Pick<Config, 'setup' | 'teardown'>> = {
  setup: [
    () => {
      console.log('在所有测试之前运行')
    }
  ],
  teardown: [
    () => {
      console.log('在所有测试之后运行')
    }
  ],
}

插件

Japa 有一个插件系统,您可以使用它来扩展其功能。插件在 tests/bootstrap.ts 文件中注册。

另请参阅:创建 Japa 插件

ts
export const plugins: Config['plugins'] = [
  assert(),
  pluginAdonisJS(app)
]

报告器

报告器用于在测试运行时报告/显示测试进度。报告器在 tests/bootstrap.ts 文件中注册。

另请参阅:创建 Japa 报告器

ts
export const reporters: Config['reporters'] = {
  activated: ['spec']
}

创建测试

您可以使用 make:test 命令创建新测试。该命令需要套件的名称来创建测试文件。

另请参阅:Make test 命令

sh
node ace make:test posts/create --suite=functional

该文件将创建在使用 files glob 属性配置的目录中。

编写测试

测试使用从 @japa/runner 包导入的 test 方法定义。测试接受标题作为第一个参数,实现回调作为第二个参数。

在以下示例中,我们创建一个新用户帐户并使用 assert 对象来确保密码正确哈希。

ts
import { test } from '@japa/runner'

import User from '#models/User'
import hash from '@adonisjs/core/services/hash'

test('创建新用户时哈希用户密码', async ({ assert }) => {
  const user = new User()
  user.password = 'secret'
  
  await user.save()
  
  assert.isTrue(hash.isValidHash(user.password))
  assert.isTrue(await hash.verify(user.password, 'secret'))
})

使用测试组

测试组使用 test.group 方法创建。组为您的测试添加结构,并允许您围绕测试运行生命周期钩子

继续上一个示例,让我们将密码哈希测试移到一个组中。

ts
import { test } from '@japa/runner'

import User from '#models/User'
import hash from '@adonisjs/core/services/hash'

// highlight-start
test.group('创建用户', () => {
// highlight-end
  test('哈希用户密码', async ({ assert }) => {
    const user = new User()
    user.password = 'secret'
    
    await user.save()
    
    assert.isTrue(hash.isValidHash(user.password))
    assert.isTrue(await hash.verify(user.password, 'secret'))
  })
// highlight-start
})
// highlight-end

如果您注意到了,我们从测试标题中删除了"创建新用户时"片段。这是因为组标题明确说明此组下的所有测试都限定于创建用户

生命周期钩子

生命周期钩子用于围绕测试执行操作。您可以使用 group 对象定义钩子。

另请参阅 - Japa 生命周期钩子文档

ts
test.group('创建用户', (group) => {
  // highlight-start
  group.each.setup(async () => {
    console.log('在每个测试之前运行')
  })

  group.each.teardown(async () => {
    console.log('在每个测试之后运行')
  })

  group.setup(async () => {
    console.log('在所有测试之前运行一次')
  })

  group.teardown(async () => {
    console.log('在所有测试之后运行一次')
  })
  // highlight-end

  test('哈希用户密码', async ({ assert }) => {
    const user = new User()
    user.password = 'secret'
    
    await user.save()
    
    assert.isTrue(hash.isValidHash(user.password))
    assert.isTrue(await hash.verify(user.password, 'secret'))
  })
})

后续步骤

现在您已了解创建和编写测试的基础知识。我们建议您在 Japa 文档中探索以下主题。

运行测试

您可以使用 test 命令运行测试。默认情况下,将执行所有套件的测试。但是,您可以通过传递名称来运行特定套件的测试。

sh
node ace test
sh
node ace test functional
node ace test unit

监视文件更改并重新运行测试

您可以使用 --watch 命令来监视文件系统并重新运行测试。如果测试文件被更改,则更改文件中的测试将运行。否则,所有测试将重新运行。

sh
node ace test --watch

过滤测试

运行测试时,您可以使用命令行标志应用过滤器。以下是可用选项列表。

另请参阅:Japa 过滤测试指南

TIP

使用 VSCode? 使用 Japa 扩展通过键盘快捷键或活动侧边栏在代码编辑器中运行选定的测试。

标志描述
--tests按测试标题过滤测试。此过滤器与确切的测试标题匹配。
--files按测试文件名的子集过滤测试。匹配针对文件名末尾进行,不包含 .spec.ts。您可以使用通配符表达式运行完整文件夹的测试。folder/*
--groups按组名过滤测试。此过滤器与确切的组名匹配。
--tags按标签过滤测试。您可以在标签名前加波浪号 ~ 以忽略具有给定标签的测试
--matchAll默认情况下,Japa 将运行匹配任何提到的标签的测试。如果您希望所有标签都匹配,则使用 --matchAll 标志

强制退出测试

Japa 在完成所有测试后等待进程正常关闭。正常关闭过程意味着退出所有长期连接并清空 Node.js 事件循环。

如果需要,您可以使用 --force-exit 标志强制 Japa 退出进程,而不等待正常关闭。

sh
node ace test --force-exit

重试测试

您可以使用 --retries 标志多次重试失败的测试。该标志将应用于所有没有在测试级别显式定义重试计数的测试。

sh
# 重试失败的测试 2 次
node ace test --retries=2

运行上次运行失败的测试

您可以使用 --failed 命令行标志重新运行上次运行失败的测试。

sh
node ace test --failed

在报告器之间切换

Japa 允许您在配置文件中注册多个测试报告器,但默认情况下不激活它们。您可以在配置文件中或使用 --reporter 命令行标志激活报告器。

sh
# 激活 spec 报告器
node ace test --reporter=spec

# 激活 spec 和 json 报告器
node ace test --reporter=spec,json

您也可以在配置文件中激活报告器。

ts
export const reporters: Config['reporters'] = {
  activated: ['spec', 'json']
}

向 Node.js 命令行传递选项

test 命令将测试 (bin/test.ts 文件) 作为子进程运行。如果您想将 node 参数传递给子进程,可以在命令名称之前定义它们。

sh
node ace --no-warnings --trace-exit test

环境变量

您可以使用 .env.test 文件来定义测试期间所需的环境变量。.env.test 中的值优先于 .env 文件中的值。

测试期间的 SESSION_DRIVER 必须设置为 memory

dotenv
// title: .env.test
SESSION_DRIVER=memory