你可以使用 Cypress 编写 UI 测试。它是一个基于 NodeJS 的
全栈测试框架,不依赖 Selenium。
要编写集成测试,请在 cypress/integration
目录中创建一个 .js 文件。
示例
以下是一个用于检查待办事项插入的集成测试示例
context('ToDo', () => {
before(() => {
cy.login('Administrator', 'admin');
cy.visit('/desk');
});
it('creates a new todo', () => {
cy.visit('/app/todo/new-todo-1');
cy.fill_field('description', 'this is a test todo', 'Text Editor').blur();
cy.get('.page-title').should('contain', 'Not Saved');
cy.get('.primary-action').click();
cy.visit('/desk#List/ToDo');
cy.location('hash').should('eq', '/app/todo');
cy.get('.list-row').should('contain', 'this is a test todo');
});
});
在本地运行 Cypress
Cypress 使用你系统上安装的任意基于 Chromium 的浏览器来运行测试。
每个应用都有自己的 Cypress 测试套件。要运行某个应用的测试,请在 frappe-bench 目录中运行
以下命令。
bench --site [sitename] run-ui-tests [app]
这将打开 Cypress Electron 界面,你可以在其中手动运行任意测试,或
运行所有测试。
你也可以在无头模式下运行测试。
# run in headless mode
bench --site [sitename] run-ui-tests [app] --headless
要启用 Cypress 并行测试,你可以传入 --parallel 标志。
有关 Cypress 并行测试工作原理的更多信息可以在此处找到。
# run tests parallelly
bench --site [sitename] run-ui-tests [app] --parallel
代码覆盖率
代码覆盖率有助于识别测试期间执行了源代码的哪些行。为了测量代码覆盖率,需要对源代码进行插桩,并且需要将此插桩后的源代码与我们的测试运行器集成,以收集覆盖率并生成报告。
对于 Frappe 中的 Cypress 测试,.js 文件使用 Istanbul 进行插桩,并使用 Cypress 代码覆盖率插件合并每个测试的覆盖率并保存合并结果。
代码插桩:
为了计算源代码的哪些行被执行了,会通过插桩向代码中插入额外的计数器。例如:
插桩前:
function foo(a, b) {
if (a < b)
return b - a;
else
return a - b;
}
插桩后:
cov_1m1jljnmzu();
function foo(a, b) {
cov_1m1jljnmzu().f[0]++;
cov_1m1jljnmzu().s[0]++;
if (a < b) {
cov_1m1jljnmzu().b[0][0]++;
cov_1m1jljnmzu().s[1]++;
return b - a;
} else {
cov_1m1jljnmzu().b[0][1]++;
cov_1m1jljnmzu().s[2]++;
return a - b;
}
}
当使用这个修改过(插桩)的源代码进行测试时,这些计数器会随着代码的执行而递增,并生成一个覆盖率对象。然后 Cypress 代码覆盖率插件会处理收集到的覆盖率并生成覆盖率报告。
在本地生成代码覆盖率报告:
- 使用 istanbul/nyc 对源代码进行插桩:
npx nyc instrument -x 'frappe/public/dist/**' -x 'frappe/public/js/lib/**' -x '**/*.bundle.js' --compact=false --in-place frappe
这会将 frappe 文件夹中的现有源代码替换为插桩后的源代码。-x 标志用于排除指定的路径。你也可以使用 -n 标志来指定要包含的路径。有关 nyc instrument 命令的更多详细信息,请参见此处
- 运行 Cypress 测试:
bench --site test_site run-ui-tests frappe --with-coverage
- 生成报告:
npx nyc report --reporter=text
有关其他报告格式,请参见此处
Testing-Library 查询
你也可以在 Cypress 测试中使用 Testing Library 查询。Testing Library 提供了以下测试工具:
- 让编写模拟用户与应用交互方式的 UI 测试变得更加容易
- 让在不需要了解所有实现细节的情况下查找 DOM 中的元素变得更加容易
- 帮助保持测试的可维护性(这样小的重构就不会破坏测试)
有关用法的更多详细信息,请参见 Testing Library 文档
Testing Library 提供了多种查询来查找页面上的元素。以下是一些示例:
- ByRole
在此处查看 HTML 元素及其默认角色的表格
| 查询 | 元素 |
|---|---|
findByRole('button', {name: 'Save'}) |
“ 且可访问名称为 ‘Save’ |
findByRole('checkbox') |
“ |
findByRole('textbox') |
, (也匹配其他默认 role=’textbox’ 的元素) |
findByRole('searchbox') |
<input type="search"> |
findByRole('listbox') |
<select></select>, “ |
- ByLabelText
| 查询 | 元素 |
|---|---|
findByLabelText('Optimize') |
与标签 ‘Optimize’ 关联的元素 |
- ByPlaceholderText
| 查询 | 元素 |
|---|---|
findByPlaceholderText('Name') |
placeholder=’Name’ 的元素 |
- ByText
| 查询 | 元素 |
|---|---|
findByText('example.json') |
textContent=’example.json’ 的元素 |
- ByDisplayValue
| 查询 | 元素 |
|---|---|
findByDisplayValue('Option 1') |
且选中的 <option></option> 为 ‘Option 1’ (也匹配值属性相符的 <input> 或 <textarea></textarea>) |
- ByTitle
| 查询 | 元素 |
|---|---|
findByTitle('Open Link') |
title=’Open Link’ 的元素 |
- ByAltText
- ByTestId