Testes de regressão com o comando run-compare

O comando run-compare PQTest é uma ferramenta poderosa para testes de regressão, permitindo-lhe avaliar minuciosamente as funções do conector e a geração do texto do comando. Para ilustrar a sua versatilidade, as secções seguintes fornecem vários exemplos adaptados a diferentes cenários.

Note

O comando run-compare substitui o comando compare anterior.

Formatos de entrada de teste

O comando run-compare suporta dois formatos de entrada de teste:

  • Formato de expressão: Uma única expressão M (por exemplo, uma let invocação de expressão ou função). Este formato é o mais simples e é adequado para a maioria dos cenários de teste.
  • Formato do documento de secção: Um documento de secção M que contém um ou mais membros de secção. Este formato é útil para testes que requerem funções auxiliares, valores partilhados ou configurações mais complexas.

Quando um ficheiro de teste utiliza o formato de expressão, o PQTest converte-o automaticamente internamente num documento de secção antes da avaliação. Também podes escrever a tua entrada de teste diretamente como um documento de secção.

Exemplo de formato de expressão

let
    Source = Contoso.Contents("TestEndpoint"),
    Result = Table.RowCount(Source)
in
    Result

Exemplo do formato do documento de secção

section Test;

shared Helper = (x) => x + 1;
shared Query = let
    Source = Contoso.Contents("TestEndpoint"),
    Result = Helper(Table.RowCount(Source))
in
    Result;

Quando é fornecida uma consulta de parâmetro, a consulta de parâmetro é adicionada como membro de secção ao documento de secção. A consulta de parâmetros é avaliada como parte da mesma secção, permitindo que a consulta de teste a faça referência direta.

Consultas básicas

A forma mais simples de teste é adicionar uma única expressão de consulta a um .query.pq ficheiro, que pode executar usando o comando run-compare . O PQTest avalia a expressão e gera um .pqout ficheiro (de saída) com o mesmo nome. Para quaisquer execuções subsequentes, compara a saída gerada pela avaliação do .query.pq ficheiro com o .pqout ficheiro (output) com o mesmo nome e devolve a saída da avaliação.

Exemplo 1 - Executar o comando run-compare para um ficheiro de consulta quando um ficheiro de saída não existe

O exemplo seguinte executa um único ficheiro de teste de consulta usando a extensão Power Query especificada e gera ficheiro de saída para comparar.

<Path to PQTest.exe>.\PQTest.exe run-compare -e contoso.mez -q contoso.query.pq
[
  {
    "Details": "Contoso.Contents(\"TestEndpoint\")",
    "EndTime": "2025-12-11T18:04:14.8991822+00:00",
    "Method": "Compare.TestFiles",
    "Name": "contoso.query.pq",
    "StartTime": "2025-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"
  }
]

Exemplo 2 - Executar o comando run-compare para um ficheiro de consulta quando um ficheiro de saída não existe e a flag FailOnMissingOutputFile está definida

<Path to PQTest.exe>.\PQTest.exe run-compare -e contoso.mez -q contoso.query.pq -fomof
[
  {
    "Details": "Contoso.Contents(\"TestEndpoint\")",
    "EndTime": "2025-12-11T18:04:14.8991822+00:00",
    "Method": "Compare.TestFiles",
    "Name": "contoso.query.pq",
    "StartTime": "2025-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"
  }
]

Exemplo 3 - Executar o comando run-compare para um ficheiro de consulta com um ficheiro de saída presente

O exemplo seguinte executa um único ficheiro de teste de consulta usando a extensão Power Query especificada, compara-o com o ficheiro de saída e devolve o resultado.

<Path to PQTest.exe>.\PQTest.exe run-compare -e contoso.mez -q contoso.query.pq
[
  {
    "Details": "Contoso.Contents(\"TestEndpoint\")",
    "EndTime": "2025-12-11T18:04:14.8991822+00:00",
    "Method": "Compare.TestFiles",
    "Name": "contoso.query.pq",
    "StartTime": "2025-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"
  }
]

Testes com consulta de parâmetros

Consulta de parâmetros é uma consulta que é combinada com uma consulta de teste em tempo de execução, com a consulta de parâmetros a ser executada primeiro. Esta funcionalidade permite dividir o ficheiro ".query.pq" em duas partes: o ficheiro de consulta de parâmetros e o ficheiro de consulta de teste.

Teste de fonte de dados independente com formato de consulta por parâmetros e testes

Um exemplo de caso de uso em que esta funcionalidade seria útil é criar um conjunto de testes independente da fonte de dados. Podes usar a tua consulta de parâmetros para recuperar dados da fonte de dados, e fazer com que a consulta de teste seja genérica M. Se quiseres executar os testes para outro conector, só precisas de adicionar/atualizar a consulta de parâmetros para apontar para essa fonte de dados específica.

Uma diferença fundamental ao usar uma consulta de parâmetros é que a consulta de teste segue um formato diferente. Em vez de ser uma expressão de fórmula, deve ser uma função M que recebe um parâmetro de entrada, que representa a tabela devolvida da consulta de parâmetros.

Quando é fornecida uma consulta de parâmetro, a consulta de parâmetros é adicionada como membro de secção ao final do documento de secção do teste. As entradas de teste e parâmetros são então avaliadas em conjunto como um único documento de secção Mashup.

Note

Se o ficheiro de consulta de parâmetros contiver erros (por exemplo, erros de sintaxe ou de avaliação), o PQTest reporta um erro descritivo indicando o problema com o ficheiro de parâmetros em vez de produzir uma falha pouco clara.

Imagina que tens a seguinte consulta de teste:

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

Para o converter numa consulta de teste e parâmetro, precisa de os dividir da seguinte forma:

Consulta de Parâmetros:

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

Consulta de Teste:

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

Exemplo 4 - Usar tanto a consulta de parâmetros como a consulta de teste com o comando run-compare

<Path to PQTest.exe>.\PQTest.exe run-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": "2025-12-11T18:04:14.8991822+00:00",
    "Method": "Compare.TestFiles",
    "Name": "contoso.query.pq",
    "StartTime": "2025-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"
  }
]

Comparação de diagnósticos

Informação adicional de diagnóstico pode ser avaliada ao usar o comando run-compare subscrevendo um canal de diagnóstico. Quando o comando run-compare é executado, o PQTest gera um .diagnostics ficheiro para cada canal subscrito que teve um evento. Para execuções subsequentes, compara o evento de diagnóstico com o respetivo .diagnostics ficheiro, semelhante a .pqout.

Exemplo 5 - Subscrever o canal de diagnóstico ODBC (Open Database Connectivity) para validar a dobra de consultas

O exemplo seguinte mostra como subscrever o canal ODBC, que captura qualquer SQL gerado pelo driver ODBC quando o dobramento de consulta é utilizado.

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

O canal de diagnóstico ODBC pode ser usado para verificar se uma consulta está a foldar e se está a gerar o SQL correto.

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

A consulta agora consolida e gera o seguinte texto de comando ODBC no ficheiro .diagnostics:

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

Usar um ficheiro de definições

Qualquer parâmetro de entrada na linha de comandos para o comando run-compare também pode ser passado através de um ficheiro de definições JSON. O JSON pode ter as seguintes opções:

Option Tipo Description
Caminhos de Extensão matriz Array de caminhos que apontam para o ficheiro conector (mez/pqx).
FalharNoFicheiroDeSaídaAusente booleano Run-compare não gera um ficheiro PQOut e falha se este não existir.
FalhaNaDobra booleano Run-compare falha se uma consulta não for completamente simplificada. Quando ativada, consultas que não podem ser totalmente integradas na fonte de dados geram um erro em vez de recorrerem à avaliação local.
ParameterQueryFilePath cadeia (de caracteres) Ficheiro de consulta que contém M expressões, que são combinadas em tempo de execução com o ficheiro de consulta de teste. Um caso de uso comum é ter um ficheiro de consulta de parâmetro único para especificar uma expressão M e recuperar os dados para múltiplas consultas de teste.
QueryFilePath cadeia (de caracteres) Ficheiro de consulta que contém a expressão M (.pq) a ser testada.
TrxReportPath cadeia (de caracteres) Gera um TRX ficheiro de resultados (Visual Studio Test Results File) e ficheiros JSON separados para cada teste num determinado caminho.
DiagnosticChannels matriz Nome dos canais de diagnóstico a serem associados ao teste (por exemplo, Odbc para capturar instruções de 'query folding').
Pasta ResultadosTesteIntermédios cadeia (de caracteres) Caminho de pasta personalizado para armazenar resultados intermédios de teste.
PersistirResultadosIntermediáriosDeTestes booleano Mantém os resultados intermédios dos testes após a execução do teste.

No caso de serem fornecidas tanto a opção de entrada na linha de comandos como a opção de definições, a entrada na linha de comandos é priorizada.

Exemplo 6 - Usar ficheiro de definições em vez de argumentos de linha de comandos

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

O comando é equivalente ao seguinte comando:

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

Onde settings.json está o seguinte ficheiro JSON:

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

Testar baterias com o comando run-compare

Uma bateria de testes é um conjunto de testes que avaliam múltiplos aspetos do seu código. Coloque os ficheiros de consulta na mesma pasta para que o PQTest os possa localizar facilmente. Em vez de passar um nome específico de ficheiro de teste, especifique o caminho da pasta e o PQTest executa todos os ficheiros de consulta de teste .query.pq numa única passagem.

Exemplo 7 - Executar uma bateria de testes

Assumindo uma pasta chamada test que contenha os seguintes ficheiros:

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

Toda a bateria de teste pode ser executada usando a seguinte linha de comandos:

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

Ignorar testes ao executar uma bateria de testes

Um teste pode ser ignorado ao executar uma bateria de testes ao alterar a extensão do ficheiro .query.pq para .query.pq.ignore.

Exemplo 8 - Ignorar um teste ao executar uma bateria de testes

Assumindo uma pasta chamada test que contenha os seguintes ficheiros:

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

Os ficheiros contoso.testa.query.pq e contoso.testc.query.pq são executados, mas contoso.testb.query.pq.ignore é ignorado quando o seguinte comando é executado para executar a bateria de teste:

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

Testes de filtragem

A --testFilter opção permite incluir ou excluir seletivamente ficheiros de teste ao executar baterias de teste. Esta opção utiliza padrões glob (curingas) para corresponder aos caminhos dos ficheiros e pode ser especificada várias vezes para criar regras complexas de filtragem.

Filtros de inclusão

Especifique quais os ficheiros a incluir no teste usando padrões padrão de globos.

<Path to PQTest.exe>.\PQTest.exe run-compare -e contoso.mez -q .\test --testFilter "Suite1/**/*.pq"

Filtros de exclusão

Especifique quais os ficheiros a excluir do teste usando o ! prefixo para indicar padrões de exclusão.

<Path to PQTest.exe>.\PQTest.exe run-compare -e contoso.mez -q .\test --testFilter "!BrokenTests/*"

Vários filtros

Múltiplas --testFilter opções podem ser combinadas para criar uma lógica de filtragem complexa:

<Path to PQTest.exe>.\PQTest.exe run-compare -e contoso.mez -q .\test --testFilter "**/*.pq" --testFilter "!BrokenTests/*" --testFilter "!**/*donotrun*.pq"

Comportamento do filtro

  • Inclusão implícita: Quando não são especificados filtros de inclusão, **/*.query.pq é aplicada automaticamente.
  • Insensível a maiúsculas: Todos os padrões correspondem sem distinção de maiúsculas e minúsculas.
  • Independente de ordem: A ordem dos filtros não afeta o resultado.
  • Formato do caminho: Use barras para frente (/) nos padrões para compatibilidade entre plataformas.

Exemplos de padrões Glob

Pattern Description
**/*.pq Todos os ficheiros .pq em qualquer diretório
**/*.query.pq Todos os .query.pq ficheiros em qualquer diretório
Suite1/**/*.pq Todos os ficheiros no diretório Suite1
**/test*.pq Todos os ficheiros .pq que começam por "test"
!BrokenTests/* Excluir todos os ficheiros no diretório BrokenTests
!**/*temp*.pq Exclua todos os .pq ficheiros que contenham "temp"
SpecificTest.pq Inclua apenas o ficheiro específico

Note

Filtros aplicam-se ao caminho relativo do diretório de consulta especificado. Um erro é devolvido se forem fornecidos filtros e o caminho do ficheiro de consulta apontar para um ficheiro específico em vez de um diretório. Use aspas em torno dos padrões para evitar a expansão da carcaça.

Listagem de ficheiros de teste sem execução

A --listOnly opção permite pré-visualizar quais os ficheiros de teste que seriam executados pelo comando run-compare sem realmente executar os testes. Esta opção é útil para verificar a descoberta de testes e o comportamento do filtro.

Exemplo 9 - Listagem de ficheiros de teste

<Path to PQTest.exe>.\PQTest.exe run-compare -e contoso.mez -q .\test --listOnly
{
    "SourcePath": "C:\\MyProject\\test",
    "TestFilters": [],
    "Tests": [
        {
            "Test": "MyTest.query.pq",
            "RelativePath": "Suite1\\MyTest.query.pq",
            "AbsolutePath": "C:\\MyProject\\test\\Suite1\\MyTest.query.pq"
        },
        {
            "Test": "AnotherTest.query.pq",
            "RelativePath": "Suite2\\AnotherTest.query.pq",
            "AbsolutePath": "C:\\MyProject\\test\\Suite2\\AnotherTest.query.pq"
        }
    ]
}

A saída contém os seguintes campos:

  • SourcePath: O valor QueryFilePath que foi fornecido ao comando a partir da opção -q.
  • TestFilters: Uma lista de todos os valores de TestFilter que foram aplicados (a partir das --testFilter opções).
  • Testes: Um array de objetos de ficheiro de teste, onde cada objeto contém:
    • Test: O nome do ficheiro de teste.
    • RelativePath: O caminho relativo ao diretório base de teste especificado por -q.
    • AbsolutePath: O caminho absoluto completo para o ficheiro de teste.

Combinação com filtros de teste

A --listOnly opção respeita todas as --testFilter opções, permitindo-lhe pré-visualizar o efeito dos seus filtros:

<Path to PQTest.exe>.\PQTest.exe run-compare -e contoso.mez -q .\test --testFilter "Suite1/**/*.pq" --listOnly

Note

Todos os filtros de teste são aplicados antes de serem listados. Não ocorre execução real de testes ao usar --listOnly.

Gestão dos resultados de testes intermédios

O comando run-compare gera ficheiros intermédios durante a execução do teste, incluindo ficheiros de saída de teste reais (.pqout) e ficheiros de diagnóstico (.diagnostics). Por defeito, estes ficheiros são criados numa localização temporária com uma estrutura de subpastas baseada em datas e são automaticamente limpos após a conclusão do teste.

Pode controlar este comportamento usando duas opções:

  • --intermediateTestResultsFolder | -itrf: Especifica um caminho de pasta personalizado para armazenar resultados intermédios de testes.
  • --persistIntermediateTestResults | -pitr: Mantém os resultados intermédios após a conclusão da execução do teste.

Exemplo 10 - Utilização de uma pasta intermédia personalizada e resultados persistentes

<Path to PQTest.exe>.\PQTest.exe run-compare -e contoso.mez -q .\test -itrf "C:\TestResults" -pitr

Estrutura intermédia de pastas

Quando especifica uma pasta intermédia de resultados de testes, o PQTest cria uma estrutura de subpastas baseada em datas para organizar os resultados dos testes:

<IntermediateTestResultsFolder>\
  └── YYYYMMDD_HHmmss_ffffff\
      ├── Test1.query.pqout
      ├── Test2.query.pqout
      ├── Test3.query.odbc.diagnostics
      └── ...

Comportamento de limpeza

O comportamento da limpeza depende de especificar uma pasta intermédia e se usar a flag persist:

Scenario Pasta Especificada Intermediária Indicador de Persistência Comportamento
1 Não Não Ficheiros criados na localização temporária, subpasta baseada em data apagada após testes
2 Sim Não Ficheiros criados numa pasta especificada, subpasta baseada em data apagada após testes
3 Não Sim Ficheiros criados na localização temporária, subpasta baseada em data apagada após testes
4 Sim Sim Ficheiros criados numa pasta especificada, subpasta baseada em data preservada

Note

Para persistir resultados intermédios, deve especificar tanto --intermediateTestResultsFolder como --persistIntermediateTestResults. O indicador --persistIntermediateTestResults por si só, sem especificar uma pasta, não guarda os resultados. Se a pasta intermédia especificada não existir, o PQTest tenta criá-la. Os caminhos relativos são suportados e resolvidos em relação ao diretório de trabalho atual.