Teste de regressão com o comando run-compare

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

Note

O comando run-compare substitui o comando de comparação anterior.

Testar formatos de entrada

O comando run-compare dá suporte a dois formatos de entrada de teste:

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

Quando um arquivo de teste usa o formato de expressão, o PQTest converte-o automaticamente em um documento de seção internamente antes da avaliação. Você também pode escrever sua entrada de teste diretamente como um documento de seção.

Exemplo de formato de expressão

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

Exemplo de formato de documento de seção

section Test;

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

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

Consultas básicas

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

Exemplo 1 – Executando o comando run-compare para um arquivo de consulta quando um arquivo de saída não existe

O exemplo a seguir executa um único arquivo de teste de consulta usando a extensão do Power Query especificada e gera um arquivo de saída a ser comparado.

<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 – Executando o comando run-compare para um arquivo de consulta quando um arquivo de saída não existe e o sinalizador FailOnMissingOutputFile é definido

<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 – Executando o comando run-compare para um arquivo de consulta com um arquivo de saída presente

O exemplo a seguir executa um único arquivo de teste de consulta usando a extensão do Power Query especificada, compara-o com o arquivo de saída e retorna 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"
  }
]

Teste com consulta de parâmetro

A consulta de parâmetro é uma consulta que é combinada com uma consulta de teste durante o tempo de execução, com a consulta de parâmetro sendo executada primeiro. Essa funcionalidade permite dividir o arquivo ".query.pq" em duas partes: o arquivo de consulta de parâmetro e o arquivo de consulta de teste.

Teste de fonte de dados independente com formato de consulta de parâmetro e teste

Um exemplo de um caso de uso em que essa funcionalidade seria útil é criar um conjunto de testes independente de fonte de dados. Você pode usar a consulta de parâmetro para recuperar dados da fonte de dados e fazer com que a consulta de teste seja genérica M. Se você quiser executar os testes para outro conector, só precisará adicionar/atualizar a consulta de parâmetro para apontar para essa fonte de dados específica.

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

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

Note

Se o arquivo de consulta de parâmetro contiver erros (por exemplo, erros de sintaxe ou erros de avaliação), o PQTest relatará um erro descritivo indicando o problema com o arquivo de parâmetro em vez de produzir uma falha não clara.

Digamos que você tenha a seguinte consulta de teste:

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

Para convertê-lo em um teste e uma consulta de parâmetro, você precisa dividi-los da seguinte maneira:

Consulta de parâmetro:

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 – Usando a consulta de parâmetro e 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"
  }
]

Comparando diagnósticos

Informações extras de diagnóstico podem ser avaliadas ao usar o comando run-compare assinando um canal de diagnóstico. Quando o comando run-compare é executado, o PQTest gera um .diagnostics arquivo para cada canal assinado que tinha um evento. Para execuções subsequentes, ele compara o evento de diagnóstico com o arquivo .diagnostics, semelhante a .pqout.

Exemplo 5 – Como assinar o canal de diagnóstico do ODBC para validar a dobragem de consultas

O exemplo a seguir mostra como assinar o canal do ODBC, que captura qualquer SQL gerado pelo driver ODBC quando a dobragem de consultas é usada.

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

O canal de diagnóstico do ODBC pode ser usado para verificar se uma consulta está sendo dobrada e se está gerando 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 é simplificada e gera o seguinte texto de comando ODBC no arquivo .diagnostics.

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

Usando um arquivo de configurações

Qualquer parâmetro de entrada de linha de comando para o comando run-compare também pode ser passado por meio de um arquivo de configurações JSON. O JSON pode ter as seguintes opções:

Opção Tipo Descrição
ExtensionPaths matriz Matriz de caminhos que apontam para o arquivo do conector (mez/pqx).
FailOnMissingOutputFile bool O run-compare não gera um arquivo PQOut e falha se ele não estiver presente.
FailOnFoldingFailure bool A comparação de execução falhará se uma consulta não dobrar completamente. Quando habilitadas, as consultas que não podem ser totalmente dobradas para a fonte de dados geram um erro em vez de voltar à avaliação local.
ParameterQueryFilePath cadeia Arquivo de consulta que contém expressões M, que é combinado em runtime com o arquivo de consulta de teste. Um caso de uso comum é ter um único arquivo de consulta de parâmetro para especificar uma expressão M para recuperar os dados de várias consultas de teste.
QueryFilePath cadeia Arquivo de consulta que contém a expressão M (.pq) a ser testada.
TrxReportPath cadeia Gera um TRX arquivo de resultados (Arquivo de Resultados de Teste do Visual Studio) e arquivos JSON separados para cada teste em um determinado caminho.
DiagnosticChannels matriz Nome dos canais de diagnóstico a serem anexados à execução de teste (por exemplo, Odbc para capturar instruções de dobragem de consulta).
PastaDeResultadosDeTesteIntermediários cadeia Caminho de pasta personalizado para armazenar resultados de teste intermediários.
PersistirResultadosIntermediáriosDeTeste bool Mantém os resultados do teste intermediário após a conclusão da execução do teste.

No caso de serem fornecidos tanto a entrada de linha de comando quanto as opções de configuração, a entrada de linha de comando é priorizada.

Exemplo 6 – Usando o arquivo de configurações em vez de argumentos de linha de comando

<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 é o seguinte arquivo JSON:

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

Testar baterias com o comando run-compare

Uma bateria de teste é uma coleção de testes que avaliam vários aspectos do seu código. Coloque os arquivos de consulta na mesma pasta para que o PQTest possa localizá-los facilmente. Em vez de passar um nome de arquivo de teste específico, especifique o caminho da pasta e o PQTest executa todos os arquivos de consulta de teste .query.pq em uma única passagem.

Exemplo 7 – Executar uma bateria de testes

Supondo que uma pasta nomeada teste contenha os seguintes arquivos:

  • 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 comando:

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

Como ignorar testes ao executar uma bateria de testes

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

Exemplo 8 – Ignorando um teste ao executar uma bateria de testes

Supondo que uma pasta nomeada teste contenha os seguintes arquivos:

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

Os arquivos 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

Filtragem de testes

A --testFilter opção permite que você inclua ou exclua seletivamente arquivos de teste ao executar baterias de teste. Essa opção usa glob patterns para corresponder a caminhos de arquivo e eles podem ser especificados várias vezes para criar regras de filtragem complexas.

Filtros de inclusão

Especifique quais arquivos incluir na execução de teste usando padrões glob.

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

Filtros de exclusão

Especifique quais arquivos excluir da execução de teste usando o ! prefixo para denotar padrões de exclusão.

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

Vários filtros

Várias --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 nenhum filtro de inclusão é especificado, **/*.query.pq é aplicado automaticamente.
  • Insensível a maiúsculas: todos os padrões correspondem sem diferenciar maiúsculas de minúsculas.
  • Ordem independente: a ordem dos filtros não afeta o resultado.
  • Formato de caminho: Use barras invertidas (/) em padrões para compatibilidade entre plataformas.

Exemplos de padrão glob

Pattern Descrição
**/*.pq Todos os .pq arquivos em qualquer diretório
**/*.query.pq Todos os .query.pq arquivos em qualquer diretório
Suite1/**/*.pq Todos os .pq arquivos no diretório Suite1
**/test*.pq Todos os .pq arquivos que começam com "test"
!BrokenTests/* Excluir todos os arquivos no diretório BrokenTests
!**/*temp*.pq Excluir todos os .pq arquivos que contêm "temp"
SpecificTest.pq Incluir somente o arquivo específico

Note

Os filtros se aplicam ao caminho relativo do diretório de consulta especificado. Um erro será retornado se os filtros forem fornecidos e o caminho do arquivo de consulta apontar para um arquivo específico em vez de um diretório. Use aspas em torno de padrões para evitar a expansão do shell.

Listando arquivos de teste sem execução

A --listOnly opção permite que você visualize quais arquivos de teste seriam executados pelo comando run-compare sem realmente executar os testes. Essa opção é útil para verificar o comportamento de descoberta e filtro de teste.

Exemplo 9 – Listar arquivos 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 para o comando (da -q opção).
  • TestFilters: uma lista de todos os valores testFilter que foram aplicados (de --testFilter opções).
  • Testes: uma matriz de objetos de arquivo de teste, em que cada objeto contém:
    • Teste: o nome do arquivo de teste.
    • RelativePath: o caminho relativo ao diretório de teste base especificado por -q.
    • AbsolutePath: o caminho absoluto completo para o arquivo de teste.

Combinação com filtros de teste

A --listOnly opção respeita todas as --testFilter opções, permitindo que você visualize o efeito de 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 da listagem. Nenhuma execução de teste real ocorre ao usar --listOnly.

Gerenciando resultados de teste intermediários

O comando run-compare gera arquivos intermediários durante a execução do teste, incluindo arquivos de saída de teste reais (.pqout) e arquivos de diagnóstico (.diagnostics). Por padrão, esses arquivos são criados em um local temporário com uma estrutura de subpasta baseada em data e são limpos automaticamente após a conclusão da execução do teste.

Você pode controlar esse comportamento usando duas opções:

  • --intermediateTestResultsFolder | -itrf: especifica um caminho de pasta personalizado para armazenar resultados de teste intermediários.
  • --persistIntermediateTestResults | -pitr: mantém os resultados intermediários após a conclusão da execução do teste.

Exemplo 10 – Usando uma pasta intermediária personalizada e resultados persistentes

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

Estrutura de pasta intermediária

Quando você especifica uma pasta de resultados de teste intermediária, o PQTest cria uma estrutura de subpasta baseada em data para organizar os resultados do teste:

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

Comportamento de limpeza

O comportamento de limpeza depende se você especifica uma pasta intermediária e se você usa o sinalizador de persistência:

Scenario Pasta Intermediária Especificada Manter Sinalizador Comportamento
1 Não Não Arquivos criados no local temporário, subpasta baseada em data excluída após testes
2 Sim Não Arquivos criados na pasta especificada, subpasta baseada em data excluída após testes
3 Não Sim Arquivos criados no local temporário, subpasta baseada em data excluída após testes
4 Sim Sim Arquivos criados na pasta especificada, subpasta baseada em data preservada

Note

Para persistir os resultados intermediários, você deve especificar ambos --intermediateTestResultsFolder e --persistIntermediateTestResults. O --persistIntermediateTestResults sinalizador por si só, sem especificar uma pasta, não persiste os resultados. Se a pasta intermediária especificada não existir, o PQTest tentará criá-la. Há suporte para caminhos relativos e são resolvidos em relação ao diretório de trabalho atual.