测试
编辑测试
编辑运行特定的 Kibana 测试
编辑下表概述了可能的测试文件位置以及如何调用它们
测试运行器 | 测试位置 | 运行器命令(工作目录为 Kibana 根目录) |
---|---|---|
Jest |
|
|
Jest (集成) |
|
|
功能测试 |
|
|
测试运行器参数:- 如果适用,可选参数 --grep=regexp
将仅运行描述与正则表达式匹配的测试或测试套件。 - [测试路径]
是测试文件的相对路径。
单元测试
编辑Kibana 主要使用 Jest 进行单元测试。每个插件或包都定义了一个 jest.config.js
,它扩展了 由 @kbn/test
包提供的预设。除非您打算运行项目中的所有单元测试,否则为要测试的插件或包提供 Jest 配置文件是最有效的。
yarn jest --config src/plugins/dashboard/jest.config.js
有一个脚本可用于在整个存储库中导航时提供更好的测试用户体验。要运行当前工作目录中的测试,请使用 yarn test:jest
。与 Jest CLI 一样,您还可以提供路径以确定要运行的测试。
kibana/src/plugins/dashboard/server$ yarn test:jest #or kibana/src/plugins/dashboard$ yarn test:jest server #or kibana$ yarn test:jest src/plugins/dashboard/server
提供给 test:jest
的任何其他选项都将传递给 Jest CLI,并且始终会输出生成的 Jest 命令。
kibana/src/plugins/dashboard/server$ yarn test:jest --coverage # is equivalent to yarn jest --coverage --verbose --config /home/tyler/elastic/kibana/src/plugins/dashboard/jest.config.js server
您可以为单个插件生成代码覆盖率报告。
yarn jest --coverage --config src/plugins/console/jest.config.js
Html 报告位于 target/kibana-coverage/jest/path/to/plugin 中
运行浏览器自动化测试
编辑查看功能测试,了解有关如何为 Kibana 核心和插件运行和开发功能测试的更多信息。
您还可以查看 Scripts README.md,了解有关使用我们提供的 node 脚本来构建 Kibana、运行集成测试以及在您开发时启动 Kibana 和 Elasticsearch 的更多信息。
更多测试信息
编辑功能测试
编辑我们使用功能测试来确保 Kibana UI 按预期工作。它通过自动化用户交互来取代数小时的手动测试。为了更好地控制我们的功能测试环境,并使其更易于插件作者访问,Kibana 使用了一个名为 FunctionalTestRunner
的工具。
运行功能测试
编辑FunctionalTestRunner
(FTR) 非常简单,其大部分功能都来自其配置文件。Kibana 存储库包含许多 FTR 配置文件,这些文件对 Kibana 服务器或 Elasticsearch 使用略有不同的配置,具有不同的测试文件,并且可能还有其他配置差异。FTR 配置文件根据测试区域和分发类型在清单文件中组织: 无服务器: - ftr_base_serverless_configs.yml - ftr_oblt_serverless_configs.yml - ftr_security_serverless_configs.yml - ftr_search_serverless_configs.yml 有状态: - ftr_platform_stateful_configs.yml - ftr_oblt_stateful_configs.yml - ftr_security_stateful_configs.yml - ftr_search_stateful_configs.yml 如果您在 Kibana 存储库之外编写插件,您将拥有自己的配置文件。有关更多信息,请参阅Kibana 存储库之外的插件的功能测试。
根据您的目标,有三种运行测试的方法
-
最简单选项
- 描述:启动 Kibana 和 Elasticsearch 服务器,然后运行测试。当多次运行测试时,这会慢得多,因为服务器的启动时间很慢。建议单次运行。
-
node scripts/functional_tests
- 在单个命令中完成所有操作,包括在本地运行 Elasticsearch 和 Kibana
- 在测试运行后销毁所有内容
- 退出代码报告测试的成功/失败
-
最适合开发
- 描述:两个命令,在单独的终端中运行,将长期运行且缓慢的组件与短暂且快速的组件分开。可以更快地重新运行测试,并且这仍然在本地运行 Elasticsearch 和 Kibana。
-
node scripts/functional_tests_server
- 启动 Elasticsearch 和 Kibana 服务器
- 启动速度慢
- 可以重复用于多次执行测试,从而在重新运行测试时节省一些时间
- 当检测到相关更改时,会自动重启 Kibana 服务器
-
node scripts/functional_test_runner
- 针对由
node scripts/functional_tests_server
启动的 Kibana 和 Elasticsearch 服务器运行测试 - 退出代码报告测试的成功或失败
- 针对由
-
自定义选项
- 描述:针对以其他方式启动的 Elasticsearch 和 Kibana 实例运行测试(例如 Elastic Cloud,或者您以其他方式管理的实例)。
- 仅执行功能测试
- Elasticsearch 和 Kibana 的 URL、凭据等通过环境变量指定
- 当针对 Elastic Cloud 实例运行时,需要额外的环境变量
TEST_CLOUD
和ES_SECURITY_ENABLED
- 您必须运行与您正在测试的 Kibana 版本相同的测试分支。要针对以前的次要版本运行,请使用选项
--es-version <实例版本>
- 要运行特定的配置,请使用选项
--config <配置文件>
-
以下是一个针对 Elastic Cloud 实例运行的示例
export TEST_KIBANA_URL=https://elastic:[email protected]:443 export TEST_ES_URL=https://elastic:[email protected]:443 export TEST_CLOUD=1 export ES_SECURITY_ENABLED=1 node scripts/functional_test_runner [--config <config>] [--es-version <instance version>]
-
或者您可以覆盖 URL 的任何或所有这些单独部分,而将其余部分保留为默认值。
export TEST_KIBANA_PROTOCOL=https export TEST_KIBANA_HOSTNAME=my-kibana-instance.internal.net export TEST_KIBANA_PORT=443 export TEST_KIBANA_USER=kibana export TEST_KIBANA_PASS=<password> export TEST_ES_PROTOCOL=http export TEST_ES_HOSTNAME=my-es-cluster.internal.net export TEST_ES_PORT=9200 export TEST_ES_USER=elastic export TEST_ES_PASS=<password> node scripts/functional_test_runner
-
Selenium 测试在 CI 上以无头模式运行。在本地,相同的测试将在真实的浏览器中执行。您可以通过设置环境变量来激活无头模式
export TEST_BROWSER_HEADLESS=1
-
如果您正在使用 Google Chrome,您可以减慢本地网络连接速度以验证测试稳定性
export TEST_THROTTLE_NETWORK=1
-
当针对 Cloud 部署运行时,某些测试不适用。要跳过不适用的测试,请使用 --exclude-tag。
node scripts/functional_test_runner --exclude-tag skipCloud node scripts/functional_test_runner --exclude-tag skipMKI
更多关于 node scripts/functional_test_runner
的信息
编辑在没有任何参数的情况下运行时,FunctionalTestRunner
会自动加载标准位置的配置,但是您可以使用 --config
标志覆盖该行为。使用多个 --config 参数列出配置。
-
--config test/functional/apps/app-name/config.js
使用配置为在 Chrome 中运行特定应用程序的 WebDriver 测试启动 Elasticsearch 和 Kibana 服务器。例如,--config test/functional/apps/home/config.js
使用配置为在 Chrome 中运行 home 应用程序的 WebDriver 测试启动 Elasticsearch 和 Kibana 服务器。 -
--config test/functional/config.firefox.js
使用配置为在 Firefox 中运行的 WebDriver 测试启动 Elasticsearch 和 Kibana 服务器。 -
--config test/api_integration/config.js
使用 api 集成测试配置启动 Elasticsearch 和 Kibana 服务器。 -
--config test/accessibility/config.ts
使用配置为使用 axe 运行可访问性审计的 WebDriver 测试启动 Elasticsearch 和 Kibana 服务器。
还有 --bail
和 --grep
的命令行标志,它们的行为与它们的 mocha 对应项相同。例如,使用 --grep=foo
仅运行与正则表达式匹配的测试。
也可以使用 --quiet
、--debug
或 --verbose
标志自定义日志记录。
还有 --include
之类的选项,仅运行单个文件或一组文件中定义的测试。
运行 node scripts/functional_test_runner --help
以查看所有可用选项。
编写功能测试
编辑环境
编辑测试是用 mocha 编写的,使用 @kbn/expect 进行断言。
我们使用 WebDriver 协议 在 Chrome 和 Firefox 中运行测试,并借助 chromedriver 和 geckodriver。当 FunctionalTestRunner
启动时,远程服务会创建一个新的 webdriver 会话,该会话将启动驱动程序和一个精简的浏览器实例。我们使用 browser
服务和 webElementWrapper
类来包装 Webdriver API。
FunctionalTestRunner
使用 babel 自动转换功能测试,以便测试可以使用与 Kibana 源代码相同的 ECMAScript 功能。请参阅 STYLEGUIDE.mdx。
定义
编辑提供程序
由 FunctionalTestRunner
运行的代码包装在一个函数中,以便可以通过配置文件传递它并进行参数化。任何这些 Provider 函数都可以是异步的,并且应该返回/解析为它们要提供的值。Provider 函数将始终使用单个参数调用:提供程序 API(请参阅Provider API 部分)。
配置提供程序
// config and test files use `export default` export default function (/* { providerAPI } */) { return { // ... } }
- 服务
- 服务是使用
FtrService
的子类创建的命名单例。测试和其他服务可以通过按名称请求来检索服务实例。除了 mocha API 之外的所有功能都通过服务公开。当您编写自己的功能测试时,请检查是否有现有的服务可以帮助您执行的交互,并为尚未在服务中编码的交互添加新服务。 - 服务提供程序
- 出于遗留目的,以及当创建
FtrService
的子类不方便时,您还可以使用“服务提供程序”创建服务。这些是创建服务实例并返回它们的函数。这些实例被缓存并提供给测试。目前,这些提供程序也可以返回服务实例的 Promise,允许服务在测试运行之前进行一些设置工作。我们希望在不久的将来完全弃用并删除对异步服务提供程序的支持,而是要求服务使用lifecycle
服务在测试之前运行设置。返回FtrService
以外类的实例的提供程序很可能在尽可能长的时间内得到支持。 - 页面对象
- 页面对象在功能上等同于服务,只是它们使用略有不同的机制加载,并且通常与服务分开定义。当您编写自己的功能测试时,您可能需要将某些服务编写为页面对象,但这不是必需的。
- 测试文件
FunctionalTestRunner
的主要目的是执行测试文件。这些文件导出一个测试提供程序,该程序会使用 Provider API 调用,但不应返回值。相反,测试提供程序使用 mocha 的 BDD 接口定义一个套件。- 测试套件
- 测试套件是通过调用
describe()
定义的测试集合,然后通过调用it()
、before()
、beforeEach()
等来填充测试和设置/拆卸钩子。每个测试文件必须只定义一个顶级测试套件,并且测试套件可以根据需要拥有任意多个嵌套的测试套件。 - 标签
-
在
describe()
函数中使用标签来对功能测试进行分组。标签包括-
ciGroup{id}
- 将测试套件分配给特定的 CI 工作程序 -
skipCloud
和skipFirefox
- 将测试套件排除在云端或 Firefox 上运行 -
includeFirefox
- 将在 Chrome 和 Firefox 上运行的测试分组
-
- 跨浏览器测试
- 在 CI 上,默认情况下所有功能测试都在 Chrome 中执行。要也在 Firefox 上运行一个套件,请分配
includeFirefox
标签
// on CI test suite will be run twice: in Chrome and Firefox describe('My Cross-browser Test Suite', function () { this.tags('includeFirefox'); it('My First Test'); }
如果测试不适用于 Firefox,请分配 skipFirefox
标签。
要在本地的 Firefox 上运行测试,请使用 config.firefox.js
node scripts/functional_test_runner --config test/functional/config.firefox.js
使用 test_user 服务
编辑测试应在正面的安全边界条件下运行,这意味着它们应使用所需的最小权限(和文档记录)运行,而不是以超级用户身份运行。这可以防止出现意外需要额外权限才能执行相同操作的回归类型。
功能 UI 测试现在默认使用名为 test_user
的用户登录,并且可以在不登录和退出的情况下动态更改此用户的角色。
为了实现这一点,引入了一个名为 createTestUserService
的新服务(请参阅 packages/kbn-ftr-common-functional-ui-services/services/security/test_user.ts
)。此测试用户服务的目的是创建测试配置文件中定义的角色,并设置 setRoles() 或 restoreDefaults()。
以下是如何设置角色的示例,如下所示
await security.testUser.setRoles(['kibana_user', 'kibana_date_nanos']);
在这里,我们将 test_user
设置为具有 kibana_user
角色,并且具有对特定数据索引 (kibana_date_nanos
) 的角色访问权限。
测试通常应在 before() 中设置 setRoles(),并在 after() 中设置 restoreDefaults()。
测试文件结构
编辑此带注释的示例文件显示了每个测试套件使用的基本结构。它首先导入 @kbn/expect
并定义其默认导出:一个匿名的测试提供程序。然后,测试提供程序为 getService()
和 getPageObjects()
函数解构 Provider API。它使用这些函数来收集此套件的依赖项。测试文件的其余部分对于 mocha.js 用户来说看起来很正常。describe()
、it()
、before()
以及其他函数用于定义通过服务和 PageObject
类型的对象来自动化浏览器的套件。
import expect from '@kbn/expect'; // test files must `export default` a function that defines a test suite export default function ({ getService, getPageObject }) { // most test files will start off by loading some services const retry = getService('retry'); const testSubjects = getService('testSubjects'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); // for historical reasons, PageObjects are loaded in a single API call // and returned on an object with a key/value for each requested PageObject const PageObjects = getPageObjects(['common', 'visualize']); // every file must define a top-level suite before defining hooks/tests describe('My Test Suite', () => { // most suites start with a before hook that navigates to a specific // app/page and restores some archives into {es} with esArchiver before(async () => { await Promise.all([ // start by clearing Saved Objects from the .kibana index await kibanaServer.savedObjects.cleanStandardList(); // load some basic log data only if the index doesn't exist esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/makelogs') ]); // go to the page described by `apps.visualize` in the config await PageObjects.common.navigateTo('visualize'); }); // right after the before() hook definition, add the teardown steps // that will tidy up {es} for other test suites after(async () => { // we clear Kibana Saved Objects but not the makelogs // archive because we don't make any changes to it, and subsequent // suites could use it if they call `.loadIfNeeded()`. await kibanaServer.savedObjects.cleanStandardList(); }); // This series of tests illustrate how tests generally verify // one step of a larger process and then move on to the next in // a new test, each step building on top of the previous it('Vis Listing Page is empty'); it('Create a new vis'); it('Shows new vis in listing page'); it('Opens the saved vis'); it('Respects time filter changes'); it(... }); }
Provider API
编辑所有提供程序的第一个也是唯一的参数是 Provider API 对象。此对象可用于加载服务/页面对象和配置/测试文件。
在配置文件中,API 具有以下属性
|
|
|
返回一个 Promise,该 Promise 将解析为 Config 实例,该实例提供 |
在服务和 PageObject 提供程序中,API 为
|
按名称加载并返回服务的单例实例 |
|
加载 |
在测试提供程序中,API 与服务提供程序 API 完全相同,但有一个附加方法
|
就地加载路径处的测试文件。使用此方法将其他文件中的套件嵌套到更高级别的套件中 |
服务索引
编辑内置服务
编辑FunctionalTestRunner
附带三个内置服务
- config
-
- 使用
config.get(path)
从配置文件中读取任何值
- 使用
- log
-
-
ToolingLog
实例是可读流。此服务提供的实例由FunctionalTestRunner
CLI 自动管道传输到 stdout -
log.verbose()
、log.debug()
、log.info()
、log.warning()
的工作方式与 console.log 完全相同,但会产生更有组织的输出
-
- lifecycle
-
- 主要用于服务中
- 公开用于基本协调的生命周期事件。处理程序可以返回 Promise 并异步解析/失败
- 阶段包括:
beforeLoadTests
、beforeTests
、beforeEachTest
、cleanup
Kibana 服务
编辑Kibana 功能测试定义了测试使用的大部分实际功能。
- browser
-
remote
服务的高级封装,它公开了可用的浏览器操作-
常用方法
-
browser.getWindowSize()
-
browser.refresh()
-
- testSubjects
-
- 测试主题是专门标记的元素,用于从测试中选择
- 尽可能使用
testSubjects
而不是 CSS 选择器 -
用法
-
使用
data-test-subj
属性标记您的测试主题<div id="container”> <button id="clickMe” data-test-subj=”containerButton” /> </div>
-
使用
testSubjects
帮助程序单击此按钮await testSubjects.click(‘containerButton’);
-
-
常用方法
-
testSubjects.find(testSubjectSelector)
- 在页面中查找测试主题;如果在一段时间后找不到,则抛出异常 -
testSubjects.click(testSubjectSelector)
- 单击页面中的测试主题;如果在一段时间后找不到,则抛出异常
-
- find
-
- 用于记录和管理超时的
remote.findBy*
方法的帮助程序 -
常用方法
-
find.byCssSelector()
-
find.allByCssSelector()
-
- 用于记录和管理超时的
- retry
-
- 用于重试操作的帮助程序
-
常用方法
-
retry.try(fn, onFailureBlock)
- 在循环中执行fn
,直到它成功或经过默认超时时间为止。可选的onFailureBlock
在每次重试尝试之前执行。 -
retry.tryForTime(ms, fn, onFailureBlock)
- 在循环中执行fn
,直到它成功或经过ms
毫秒为止。可选的onFailureBlock
在每次重试尝试之前执行。
-
- kibanaServer
-
- 用于与 Kibana 服务器交互的帮助程序
-
常用方法
-
kibanaServer.uiSettings.update()
-
kibanaServer.version.get()
-
kibanaServer.status.getOverallState()
-
- esArchiver
-
- 加载/卸载使用
esArchiver
创建的存档 -
常用方法
-
esArchiver.load(path)
-
esArchiver.loadIfNeeded(path)
-
esArchiver.unload(path)
-
- 加载/卸载使用
可以在此处找到功能测试中使用的所有服务列表:test/functional/services
- 底层实用程序
-
-
es
- Elasticsearch 客户端
- 更高级别的选项:
kibanaServer.uiSettings
或esArchiver
-
remote
- WebDriver 类的实例
- 负责与浏览器的所有通信
- 要执行浏览器操作,请使用
remote
服务 - 要搜索和操作 DOM 元素,请使用
testSubjects
和find
服务 - 请参阅 selenium-webdriver 文档以获取完整的 API。
-
自定义服务
编辑服务是有意为通用的。它们可以是字面上的任何东西(甚至什么都不是)。某些服务具有用于与特定类型 UI 元素(如 pointSeriesVis
)交互的帮助程序,而另一些服务则更基础,如 log
或 config
。当您想在可重用包中提供某些功能时,请考虑创建自定义服务。
要创建自定义服务 somethingUseful
-
创建一个类似于此的
test/functional/services/something_useful.js
文件// Services are defined by Provider functions that receive the ServiceProviderAPI export function SomethingUsefulProvider({ getService }) { const log = getService('log'); class SomethingUseful { doSomething() { } } return new SomethingUseful(); }
- 从
services/index.js
重新导出您的提供程序 -
将其导入到
src/functional/config.base.js
并将其添加到服务配置中import { SomethingUsefulProvider } from './services'; export default function () { return { // … truncated ... services: { somethingUseful: SomethingUsefulProvider } } }
PageObjects
编辑每个 PageObject 的目的都非常不言自明。可视化 PageObject 提供了用于与可视化应用程序交互的帮助程序,仪表板对于仪表板应用程序来说是相同的,依此类推。
一个例外是“common” PageObject。作为 intern 实现的遗留问题,“common” PageObject 是跨页面有用的帮助程序集合。既然我们有了可共享的服务,并且这些服务可以与其他 FunctionalTestRunner
配置共享,我们将继续将功能从 common PageObject 移到服务中。
请将新方法添加到现有或新服务,而不是进一步扩展 CommonPage 类。
陷阱
编辑请记住,您不能在文件中运行单个测试(it
块),因为需要按顺序运行整个 describe
。一个文件中应该只有一个顶级 describe
。
功能测试时间
编辑另一个需要注意的重要问题是通过注意时间来编写稳定的测试。 remote
上的所有方法都是异步运行的。最好编写交互,等待 UI 上出现更改后再进行下一步操作。
例如,与其编写一个简单地单击按钮的交互,不如编写一个具有更高层次目标的交互
错误示例:PageObjects.app.clickButton()
class AppPage { // what can people who call this method expect from the // UI after the promise resolves? Since the reaction to most // clicks is asynchronous the behavior is dependent on timing // and likely to cause test that fail unexpectedly async clickButton () { await testSubjects.click(‘menuButton’); } }
正确示例:PageObjects.app.openMenu()
class AppPage { // unlike `clickButton()`, callers of `openMenu()` know // the state that the UI will be in before they move on to // the next step async openMenu () { await testSubjects.click(‘menuButton’); await testSubjects.exists(‘menu’); } }
以这种方式编写可以确保您的测试时间不会出现不稳定的情况,或者基于交互后 UI 更新的假设。
调试
编辑从命令行运行
node --inspect-brk scripts/functional_test_runner
这将打印出一个 URL,您可以在 Chrome 中访问该 URL 并调试浏览器中的功能测试。
您还可以通过使用 --debug
或 --verbose
标志运行 FunctionalTestRunner
在终端中查看其他日志。 使用测试中的语句添加更多日志,例如
// load the log service const log = getService(‘log’); // log.debug only writes when using the `--debug` or `--verbose` flag. log.debug(‘done clicking menu’);
MacOS 测试性能提示
编辑在具有独立显卡的机器上的 macOS 用户可以通过更改终端模拟器的 GPU 设置来显著提高测试速度(高达 2 倍)。在 iTerm2 中:* 打开首选项(Command + ,) * 在“常规”选项卡中,“魔术”部分下,确保选中“GPU 渲染” * 打开“高级 GPU 设置…” * 取消选中“优先使用集成显卡而不是独立显卡”选项 * 重启 iTerm
不稳定测试运行器
编辑如果您的功能测试不稳定,那么运营团队可能会跳过它们,并要求您在再次启用它们之前使其不那么不稳定。此过程通常包括查看相关 Github 问题中记录的失败情况,并查找需要在测试中某个时刻等待的不正确的假设或条件。为了确定您的更改是否降低了测试失败的频率,您可以在不稳定测试运行器中运行测试。此工具最多运行特定 ciGroup 的 500 次执行。要启动不稳定测试运行器的构建,请使用您的更改创建一个 PR,然后访问 https://ci-stats.kibana.dev/trigger_flaky_test_runner,选择您的 PR,选择您的测试所在的 CI 组,然后触发构建。
这将带您到 Buildkite,您的构建将在其中运行,并告诉您是否在任何执行中失败。
一个不稳定的测试可能只在 1000 次运行中失败一次,因此请记住这一点,并确保您使用足够的执行次数来真正证明测试不再不稳定。
单元测试框架
编辑Kibana 使用 Jest
进行单元测试。
Jest
编辑Jest 测试存储在与源代码文件相同的目录中,后缀为 .test.{js,mjs,ts,tsx}
。
每个插件和包都包含自己的 jest.config.js
文件来定义其根目录,以及对 @kbn/test
提供的 jest 预设的任何覆盖。在处理单个插件或包时,您会发现运行 Jest 时提供配置文件会更有效。
yarn jest --config src/plugins/discover/jest.config.js
编写 Jest 单元测试
编辑为了编写这些测试,您需要注意两件事。第一个是 jest.mock
和 jest.doMock
之间的区别,第二个是我们的 jest 模拟文件模式
。由于我们使用 babel-jest
运行 js
和 ts
测试文件,因此两种技术都是必需的,特别是对于在 Typescript 中实现的测试,以利用自动类型推断功能。
Jest.mock 与 Jest.doMock
编辑这两种方法本质上是相同的,但是 jest.mock
调用将被提升到文件顶部,并且只能引用以 mock
为前缀的变量。另一方面,jest.doMock
不会被提升,并且可以引用我们想要的几乎任何变量,但是我们必须确保这些引用的变量在我们需要的时刻实例化,这使我们进入下一节,我们将讨论我们的 jest 模拟文件模式。
Jest 模拟文件模式
编辑特别是在 typescript 中,在单元测试中非常常见的是 jest.doMock
调用,该调用引用例如导入的类型。执行此操作将引发任何错误,但是测试将失败。原因在于,尽管 jest.doMock
不会被 babel-jest
提升,但是我们引用的类型的导入将被提升到顶部,并且在我们调用该函数时,该变量将不会被定义。
为了防止这种情况发生,我们制定了一项协议,应遵循该协议
- 每个模块都可以在
mymodule.mock.ts
中提供标准模拟,以防其他测试可以从此处使用定义中受益。此文件将没有任何jest.mock
调用,只有虚拟对象。 - 每个测试都在
mymodule.test.mocks.ts
中定义其模拟。此文件可以从通用模块的模拟文件(*.mock.ts)
中导入相关的模拟,并为每个模拟调用jest.mock
。如果有任何相关的虚拟模拟对象需要通用化(并供其他测试使用),则可以直接在此文件中定义虚拟对象。 - 每个测试都将从测试模拟文件 mymodule.test.mocks.ts 中导入其模拟。
mymodule.test.ts
的导入如下:import * as Mocks from './mymodule.test.mocks'
、import { mockX } from './mymodule.test.mocks'
或仅import './mymodule.test.mocks'
(如果没有导出任何要使用的内容)。
调试单元测试
编辑标准的 yarn test
任务运行多个子任务,可能需要几分钟才能完成,这使得调试失败非常痛苦。为了减轻痛苦,专门的任务提供了运行测试的替代方法。
您还可以添加 --debug
选项,以便使用 --inspect-brk
标志运行 node
。您需要连接一个远程调试器,例如 node-inspector
,才能在此模式下继续。
单元测试插件
编辑即使在使用 Kibana 插件生成器 时,我们也没有强制要求对插件进行单元测试的方法。请自行设置并使用您选择的工具。如果该插件将位于 Kibana 代码库中,则必须使用 Jest
。
自动辅助功能测试
编辑要编写辅助功能测试,请使用提供的辅助功能服务 getService('a11y')
。辅助功能测试的编写非常简单,因为 axe 完成了大部分繁重的工作。导航到您需要测试的 UI,然后从先前导入的服务中调用 testAppSnapshot();
,以确保 axe 未发现任何故障。浏览 UI 的每个部分以获得最佳覆盖率。
一个示例测试可能如下所示
export default function ({ getService, getPageObjects }) { const { common, home } = getPageObjects(['common', 'home']); const a11y = getService('a11y'); /* this is the wrapping service around axe */ describe('Kibana Home', () => { before(async () => { await common.navigateToApp('home'); /* navigates to the page we want to test */ }); it('Kibana Home view', async () => { await retry.waitFor( 'home page visible', async () => await testSubjects.exists('homeApp') ); /* confirm you're on the correct page and that it's loaded */ await a11y.testAppSnapshot(); /* this expects that there are no failures found by axe */ }); /** * If these tests were added by our QA team, tests that fail that require significant app code * changes to be fixed will be skipped with a corresponding issue label with more info */ // Skipped due to https://github.com/elastic/kibana/issues/99999 it.skip('all plugins view page meets a11y requirements', async () => { await home.clickAllKibanaPlugins(); await a11y.testAppSnapshot(); }); /** * Testing all the versions and different views of of a page is important to get good * coverage. Things like empty states, different license levels, different permissions, and * loaded data can all significantly change the UI which necessitates their own test. */ it('Add Kibana sample data page', async () => { await common.navigateToUrl('home', '/tutorial_directory/sampleData', { useActualUrl: true, }); await a11y.testAppSnapshot(); }); }); }
运行测试
编辑要在本地运行测试
-
在一个终端窗口中运行
node scripts/functional_tests_server --config test/accessibility/config.ts
-
当服务器打印出它已准备就绪时,在另一个终端窗口中运行
node scripts/functional_test_runner.js --config test/accessibility/config.ts
要运行 x-pack 测试,请将配置文件替换为 x-pack/test/accessibility/apps/{group1,group2,group3}/config.ts
。
测试是使用 axe 完成的。您可以使用浏览器插件运行与 CI 运行的相同内容
失败分析
编辑如果您以前从未见过失败,则失败可能会让人感到困惑。以下是来自 CI 的失败可能看起来的分解
1) Dashboard create dashboard button: Error: a11y report: VIOLATION [aria-hidden-focus]: Ensures aria-hidden elements do not contain focusable elements Help: https://dequeuniversity.com/rules/axe/3.5/aria-hidden-focus?application=axeAPI Elements: - <span aria-hidden="true"><button type="button">Submit</button></span> at Accessibility.testAxeReport (test/accessibility/services/a11y/a11y.ts:90:15) at Accessibility.testAppSnapshot (test/accessibility/services/a11y/a11y.ts:58:18) at process._tickCallback (internal/process/next_tick.js:68:7)
- “Dashboard”和“create dashboard button”是失败的测试套件和特定测试的名称。
- 始终在括号中,“[aria-hidden-focus]”是失败的 axe 规则的名称,后跟简短的描述。
- “帮助:<url>”链接到该规则的 axe 文档,包括严重性、补救技巧以及好坏代码示例。
- “元素:”指向 DOM 中发生失败的位置(使用 HTML 语法)。在此示例中,问题来自具有
aria-hidden="true"
属性和嵌套的<button>
标记的 span。如果选择器过于复杂而无法找到问题的根源,请使用前面提到的浏览器插件来定位它。如果您大致知道问题出在哪里,也可以尝试向页面添加唯一的 ID 以缩小位置范围。 - 堆栈跟踪指向 axe 的内部。堆栈跟踪的存在是为了防止测试失败是 axe 中的错误而不是您的代码中的错误,尽管这种情况不太可能发生。
包测试
编辑打包测试使用 Vagrant 虚拟机作为主机,并使用 Ansible 进行配置和断言。Kibana 发行版从目标文件夹复制到每个 VM 中并安装,同时安装所需的依赖项。
设置
编辑-
# Ubuntu sudo apt-get install python3-pip libarchive-tools pip3 install --user ansible # Darwin brew install python3 pip3 install --user ansible
- Vagrant
- Virtualbox
机器
编辑主机名 | IP | 描述 |
---|---|---|
deb |
192.168.56.5 |
安装 Kibana 的 deb 包 |
rpm |
192.168.56.6 |
安装 Kibana 的 rpm 包 |
docker |
192.168.56.7 |
安装 Kibana 的 docker 镜像 |
运行
编辑# Build distributions node scripts/build --all-platforms --debug cd test/package # Setup virtual machine and networking vagrant up <hostname> --no-provision # Install Kibana and run OS level tests # This step can be repeated when adding new tests, it ensures machine state - installations won't run twice vagrant provision <hostname> # Running functional tests node scripts/es snapshot \ -E network.bind_host=127.0.0.1,192.168.56.1 \ -E discovery.type=single-node \ --license=trial TEST_KIBANA_URL=http://elastic:changeme@<ip>:5601 \ TEST_ES_URL=http://elastic:[email protected]:9200 \ node scripts/functional_test_runner.js --include-tag=smoke
清理
编辑vagrant destroy <hostname>
跨浏览器兼容性
编辑在 OS X 上测试 IE
注意:从 7.9 版本开始不支持 IE11。
- 下载 VMWare Fusion.
- 下载适用于 VMWare 的 IE 虚拟机。
- 打开 VMWare 并转到“窗口”>“虚拟机库”。解压缩虚拟机并将 .vmx 文件拖到您的虚拟机库中。
- 右键单击您刚添加到库中的虚拟机,然后选择“
快照…
”,然后单击打开的模式窗口中的“拍摄
”按钮。当 VM 在 90 天后过期时,您可以回滚到此快照。 - 在“系统偏好设置”>“共享”中,将您的计算机名称更改为简单的名称,例如“
computer
”。 - 使用
yarn start --host=computer.local
运行 Kibana (将 computer.local 替换为你的计算机名称)。 - 现在你可以运行你的虚拟机,打开浏览器,并导航到
http://computer.local:5601
来测试 Kibana。 - 或者你可以使用 browserstack。