跳至主要内容

测试数据查询

简介

查询编辑器是数据源插件的核心部分,因为用户在此处创建用于获取数据的查询。您的数据源插件可以提供丰富的查询编辑器,允许针对不同 API 的各种查询类型。您的查询编辑器甚至可以具有可视化查询构建器、IntelliSense 和自动完成功能等特性。

隔离测试查询编辑器的部分

在以下示例中,查询编辑器通过对 /regions 的请求加载区域,并在将它们填充到下拉菜单之前过滤掉包含 gov 的区域。

The <page>.mockResourceResponse 方法允许您模拟对数据源 资源 API 的请求的响应。为了测试过滤是否按预期工作,我们使用此方法模拟 /regions 响应,并断言当单击区域下拉菜单时,仅显示名称中不包含 -gov- 的区域。

queryEditor.spec.ts
test('should filter out govcloud regions', async ({ panelEditPage, selectors, readProvisionedDataSource }) => {
const regionsMock = ['us-gov-west-1', 'us-east-1', 'us-west-1', 'us-gov-east-1'];
const expectedRegions = ['us-east-1', 'us-west-1'];
const ds = await readProvisionedDataSource({ fileName: 'datasources.yaml' });
await panelEditPage.datasource.set(ds.name);
await panelEditPage.mockResourceResponse('regions', regionsMock);
await panelEditPage.getQueryEditorRow('A').getByText('Regions').click();
await expect(panelEditPage.getByGrafanaSelector(selectors.components.Select.option)).toHaveText(expectedRegions);
});

测试整个数据流

以下示例显示了一个集成测试,该测试测试插件的整个查询数据流。

警告

在端到端测试中访问第三方 API 可能很有用,但它也可能存在安全问题,并可能导致 CI 管道的不可靠性。您应该始终仔细考虑并考虑使用模拟代替。

queryEditor.spec.ts
test('data query should be successful when the query is valid', async ({
panelEditPage,
readProvisionedDataSource,
}) => {
const ds = await readProvisionedDataSource({ fileName: 'datasources.yaml' });
await panelEditPage.datasource.set(ds.name);
await panelEditPage.getQueryEditorRow('A').getByText('Query Text').fill('SELECT * FROM dataset');
await expect(panelEditPage.refreshPanel()).toBeOK();
});

进行面板数据断言

在许多情况下,断言数据查询响应是否正常不足以说明您的数据源插件是否正常运行。您还必须对面板中显示的数据进行断言。

Grafana 带有一组内置面板,并且 Grafana 插件目录 中提供了各种社区面板。每个面板都可以以不同的方式呈现数据,因此不可能为所有面板提供一致的方式来断言显示的数据。因此,我们建议您为此使用 Table 面板。

The <page>.panel.data 属性返回一个 Playwright 定位器,该定位器解析一个或多个包含当前在 Table 面板中显示的值的元素。这意味着您可以使用任何接受定位器作为接收类型的自动重试 匹配器

queryEditor.spec.ts
test('data query should return values 10 and 20', async ({ panelEditPage, readProvisionedDataSource }) => {
const ds = await readProvisionedDataSource({ fileName: 'datasources.yml' });
await panelEditPage.datasource.set(ds.name);
await panelEditPage.setVisualization('Table');
await expect(panelEditPage.refreshPanel()).toBeOK();
await expect(panelEditPage.panel.data).toContainText(['10', '20']);
});

如果要断言 Table 面板中显示的列标题是什么,可以使用 <page>.panel.fieldNames 属性。

queryEditor.spec.ts
test('data query should return headers  and 3', async ({ panelEditPage, readProvisionedDataSource }) => {
const ds = await readProvisionedDataSource({ fileName: 'datasources.yml' });
await panelEditPage.datasource.set(ds.name);
await panelEditPage.setVisualization('Table');
await expect(panelEditPage.refreshPanel()).toBeOK();
await expect(panelEditPage.panel.fieldNames).toHaveText(['Stockholm', 'Vienna']);
});

在已预配的仪表盘中测试查询

有时您可能希望打开已存在面板的面板编辑页面并运行查询以确保一切按预期工作。

test('query in provisioned dashboard should return temp and humidity data', async ({
readProvisionedDashboard,
gotoPanelEditPage,
}) => {
const dashboard = await readProvisionedDashboard({ fileName: 'dashboard.json' });
const panelEditPage = await gotoPanelEditPage({ dashboard, id: '3' });
await expect(panelEditPage.refreshPanel()).toBeOK();
await expect(panel.fieldNames).toContainText(['temperature', 'humidity']);
await expect(panel.data).toContainText(['25', '10']);
});

您还可以打开已存在的仪表盘并验证表面板是否已呈现您期望的数据。

test('getting panel by id', async ({ gotoDashboardPage, readProvisionedDashboard }) => {
const dashboard = await readProvisionedDashboard({ fileName: 'dashboard.json' });
const dashboardPage = await gotoDashboardPage(dashboard);
const panel1 = await dashboardPage.getPanelById('3');
await expect(panel1.data).toContainText(['25', '32', 'staging']);
const panel2 = await dashboardPage.getPanelByTitle('Basic table example');
await expect(dashboardPage.panel2.fieldNames).toContainText(['Tokyo', 'Berlin']);
});