使用比较命令进行回归测试

PQTest 比较命令是一款功能强大的回归测试工具,可让你全面求值连接器的功能并生成命令文本。 为了说明其用途广泛,后续部分将会提供针对于不同应用场景的多种示例。

基本查询

最简单的测试方式是向 .query.pq 文件添加单个查询表达式,可以使用比较命令来执行此操作。 PQTest 会对表达式进行求值并生成使用相同名称的 .pqout(输出)文件。 对于任何后续运行,它会将 .query.pq 文件的评估中生成的输出与使用相同名称的 pqout(输出)文件进行比较,然后返回评估输出。

示例 1 - 当输出文件不存在时,为查询文件运行比较命令

以下示例使用指定的 Power Query 扩展执行单一查询测试文件,并生成要比较的输出文件。

<Path to PQTest.exe>.\PQTest.exe compare -e contoso.mez -q contoso.query.pq
[
  {
    "Details": "Contoso.Contents(\"TestEndpoint\")",
    "EndTime": "2020-12-11T18:04:14.8991822+00:00",
    "Method": "Compare.TestFiles",
    "Name": "contoso.query.pq",
    "StartTime": "2020-12-11T18:04:11.1532388+00:00",
    "Output": [
      {
        "SourceFilePath": "contoso.query.pq",
        "OutputFilePath": "contoso.query.pqout",
        "Status": "Output File Generated",
        "SerializedSource": null,
        "SourceError": null,
        "OutputError": null
      }
    ],
    "Status": "Passed",
    "Type": "PQTest.Expression"
  }
]

示例 2 - 当输出文件不存在且已设置 FailOnMissingOutputFile 标志时,为查询文件运行比较命令

<Path to PQTest.exe>.\PQTest.exe compare -e contoso.mez -q contoso.query.pq -fomof
[
  {
    "Details": "Contoso.Contents(\"TestEndpoint\")",
    "EndTime": "2020-12-11T18:04:14.8991822+00:00",
    "Method": "Compare.TestFiles",
    "Name": "contoso.query.pq",
    "StartTime": "2020-12-11T18:04:11.1532388+00:00",
    "Output": [
      {
        "SourceFilePath": "contoso.query.pq",
        "OutputFilePath": "contoso.query.pqout",
        "Status": "Missing Output File",
        "SerializedSource": "Output of contoso.query.pq",
        "SourceError": null,
        "OutputError": null
      }
    ],
    "Status": "Failed"
    "Type": "PQTest.Expression"
  }
]

示例 3 - 当存在输出文件时,为查询文件运行比较命令

以下示例使用指定的 Power Query 扩展执行单一查询测试文件,并将其与输出文件进行比较并返回结果。

<Path to PQTest.exe>.\PQTest.exe compare -e contoso.mez -q contoso.query.pq
[
  {
    "Details": "Contoso.Contents(\"TestEndpoint\")",
    "EndTime": "2020-12-11T18:04:14.8991822+00:00",
    "Method": "Compare.TestFiles",
    "Name": "contoso.query.pq",
    "StartTime": "2020-12-11T18:04:11.1532388+00:00",
    "Output": [
      {
        "SourceFilePath": "contoso.query.pq",
        "OutputFilePath": "contoso.query.pqout",
        "Status": "Passed",
        "SerializedSource": null,
        "SourceError": null,
        "OutputError": null
      }
    ],
    "Status": "Passed",
    "Type": "PQTest.Expression"
  }
]

使用参数查询进行测试

参数查询是一种结合了运行时测试查询的查询,首先会运行参数查询。 此功能让你可将 PQ/测试查询文件拆分成两个部分:参数查询文件,以及测试查询文件。

利用参数和测试查询格式进行不可知数据源的测试

此功能非常有用的用例示例是创建数据源不可知的测试套件。 可以使用参数查询检索数据源中的数据,让测试查询变为通用 M。如果想要为另一个连接器运行测试,仅需要添加/更新参数查询以指向具体的数据源。

使用参数查询时的主要区别在于测试查询遵循不同的格式。 它不能是公式表达式,而必须是提取代表从参数查询返回的表的一个输入参数的 M 函数。

假设你有以下测试查询:

let
    Source = Snowflake.Databases("...", "..."),
    Database = Source{[Name="...",Kind="Database"]}[Data],
    SelectColumns = Table.RemoveColumns(Database, { "Data" })
in
    SelectColumns

若要将其转换为测试和参数查询,需要按如下所示对其进行拆分:

参数查询:

let
    Source = Snowflake.Databases("...", "..."),
    Database = Source{[Name="...",Kind="Database"]}[Data],
    Schema = Database{[Name="...",Kind="Schema"]}[Data],
    Taxi_Table = Schema{[Name="...",Kind="Table"]}[Data],
in
    Taxi_Table

测试查询:

(Source) => let
    SelectColumns = Table.RemoveColumns(Source, { "VendorID" })
in
    SelectColumns

示例 4 - 通过比较命令同时使用参数查询和测试查询

<Path to PQTest.exe>.\PQTest.exe compare -e contoso.mez -q contoso.query.pq -pa contoso.parameter.pq
[
  {
    "Details": "(Source) => let\r\n    Schemas = Table.RemoveColumns(Source, { \"Data\" })\r\nin\r\n    Schemas",
    "EndTime": "2020-12-11T18:04:14.8991822+00:00",
    "Method": "Compare.TestFiles",
    "Name": "contoso.query.pq",
    "StartTime": "2020-12-11T18:04:11.1532388+00:00",
    "Output": [
      {
        "SourceFilePath": "contoso.query.pq",
        "OutputFilePath": "contoso.query.pqout",
        "Status": "Passed",
        "SerializedSource": null,
        "SourceError": null,
        "OutputError": null
      }
    ],
    "Status": "Passed",
    "Type": "PQTest.Expression"
  }
]

比较诊断

通过订阅诊断频道,可在使用比较命令时评估额外的诊断信息。 运行比较命令时,PQTest 会为具有事件的每个已订阅的通道输出一个 .diagnostics 文件。 对于任何后续运行,它会将诊断事件与其 .diagnostics 文件(类似于 .pqout)进行比较。

示例 5 - 订阅 ODBC(开放式数据库连接)诊断频道以验证查询折叠

以下示例演示如何订阅 ODBC 通道,此操作会在使用查询折叠时捕获 ODBC 驱动程序生成的任何 SQL。

<Path to PQTest.exe>.\PQTest.exe compare -e contoso.mez -q contoso.query.pq -dc "Odbc"

ODBC 诊断通道可用于验证查询是否折叠,以及是否生成正确的 SQL。

let
    Source = AzureSpark.Tables("...")
    T1 = Source{[Schema="default",Item="DATABASE"]}[Data],
    SelectColumns = Table.Group(T1, {}, {{"Maximum", each List.Max([number_column]), type number}}),
    FirstN = Table.FirstN(SelectColumns, 1)
in
    FirstN

现在,查询会在 .diagnostics 文件中生成以下 ODBC 命令文本:

[
  {
    "Command": "DESCRIBE default.DATABASE;"
  },
  {
    "Command": "select top 1 max(`number_column`) as `C1` from `SPARK`.`default`.`DATABASE`"
  }
]

使用设置文件

也可通过 JSON 设置文件传递任何命令行输入参数供比较命令使用。 JSON 文件可能包括下列选项:

选项 类型 描述
ExtensionPath array 指向连接器文件 (mez/pqx) 的路径数组。
FailOnMissingOutputFile bool 比较不生成 PQOut,如果不存在则失败。
FailOnFoldingFailure bool 如果引发查询折叠错误,则比较失败。
ParameterQueryFilePath 字符串 包含 M 表达式的查询文件在运行时与测试查询文件结合在一起。 常见用例为有单个参数查询文件指定 M 表达式检索多个测试查询的数据。
QueryFilePath 字符串 包含要进行测试的 M 表达式 (.pq) 的查询文件。
TrxReportPath 字符串 为给定路径中每个测试生成一个 TRX(Visual Studio 测试结果文件),并分隔 JSON 文件。
DiagnosticChannels array 要附加到测试运行的诊断通道的名称(例如,用于捕获查询折叠语句的 Odbc)。

如果同时提供有命令行输入和设置选项,则优先命令行输入。

示例 6 - 使用设置文件而不是命令行参数

<Path to PQTest.exe>.\PQTest.exe compare -e contoso.mez -q contoso.query.pq -fomof

以上命令等效于以下命令:

<Path to PQTest.exe>.\PQTest.exe compare -sf settings.json

当 setting.json 是以下 JSON 文件时:

{
  "ExtensionPaths": ["contoso.mez"],
  "QueryFilePath": "contoso.query.pq",
  "FailOnMissingOutputFile": true
}

使用比较命令测试电池

测试电池是一系列测试,用于评估代码的多个方面。 将查询文件放在同一文件夹中,以便 PQTest 可以轻松找到。 指定文件夹路径,而不是传递特定的测试文件名,PQTest 在单个传递中执行所有 .query.pq 测试查询文件。

示例 7 - 运行测试电池

假设名为测试的文件夹包含以下文件:

  • contoso.testa.query.pq
  • contoso.testb.query.pq
  • contoso.testc.query.pq

可以使用以下命令行运行整个测试电池:

<Path to PQTest.exe>.\PQTest.exe compare -e contoso.mez -q .\test

运行测试电池时忽略测试

通过将 .query.pq 文件的扩展名更改为 .query.pq.ignore 来运行测试电池时,可以忽略测试。

示例 8 - 运行测试电池时忽略测试

假设名为测试的文件夹包含以下文件:

  • contoso.testa.query.pq
  • contoso.testb.query.pq.ignore
  • contoso.testc.query.pq

虽然 contoso.testa.query.pq 和 contoso.testc.query.pq 文件已运行,但在执行以下命令以运行测试电池时忽略 contoso.testb.query.pq.ignore:

<Path to PQTest.exe>.\PQTest.exepqtest.exe compare -e contoso.mez -q .\test