Aprende sobre geradores de testes

Aprende como o percurso de Clojure usa geradores de testes para gerar testes para os exercícios


O track de Clojure usa um gerador de testes para gerar automaticamente os testes dos exercícios de prática. Baseia-se no facto de que a maioria dos exercícios definidos no repositório problem-specifications também tem um ficheiro canonical-data.json, com valores de entrada e de saída de teste normalizados que podem ser usados para implementar o exercício.

Passos

Para gerar os testes de um exercício de prática, o gerador de testes:

  1. Lê os casos de teste do exercício a partir do seu ficheiro canonical-data.json
  2. Usa o ficheiro tests.toml para omitir e excluir casos de teste
  3. Transforma os casos de teste (opcional)
  4. Renderiza os casos de teste com o template do gerador do exercício
  5. Formata o template renderizado com o cljfmt
  6. Escreve o template formatado no ficheiro de teste do exercício

Passo 1: ler o ficheiro canonical-data.json

O gerador de testes analisa os casos de teste do ficheiro canonical-data.json do exercício com a biblioteca clojure/data.json.

Como alguns dados canónicos usam aninhamento, o caso de teste analisado inclui um campo path adicional, que contém as propriedades description de quaisquer elementos pais, bem como a própria propriedade description do caso de teste.

Nota: as chaves são analisadas como keywords.

Passo 2: omitir os testes excluídos do ficheiro tests.toml

Cada exercício tem um ficheiro tests.toml, no qual os testes individuais podem ser excluídos/desativados. O gerador de testes remove os casos de teste que estejam marcados como excluídos (include = false).

Passo 3: transformar os casos de teste (opcional)

Alguns exercícios podem precisar de alguns ajustes antes de renderizar os dados. Por exemplo, podes querer tornar a descrição menos verbosa.

Para ajustar os casos de teste, define um ficheiro .meta/generator.clj com um namespace <slug>-generator. Há duas formas de transformar os casos de teste:

  • Atualizar caso(s) de teste
  • Adicionar/remover caso(s) de teste

Atualizar caso(s) de teste

Para atualizar casos de teste individuais, define a seguinte função:

(defn update-test-case
  "Update a test case"
  [test-case]
  ;; function body
)
Exemplo

Este exemplo remove todos os elementos exceto o último do valor de :path (encurtando a descrição):

(ns difference-of-squares-generator)

(defn update-test-case [test-case]
  (update test-case :path #(take-last 1 %)))

Adicionar ou remover caso(s) de teste

Para adicionar ou remover casos de teste, define a seguinte função:

(defn add-remove-test-cases
  "Add/remove test case(s)"
  [test-cases]
  ;; function body
)
Note

Se definires ambas as funções, add-remove-test-cases é chamada primeiro e update-test-case depois.

Passo 4: renderizar os casos de teste

Os casos de teste (potencialmente transformados) são depois passados ao ficheiro .meta/generator.tpl, que define como os testes devem ser renderizados com base nesses casos de teste.

Passo 5: formatar o template renderizado com o cljfmt

O template renderizado é depois formatado com o cljfmt. Isto traz as seguintes vantagens:

  • Os exercícios ficam formatados de forma consistente
  • Não precisas de te preocupar muito com espaços em branco e alinhamento quando escreves templates

Passo 6: escrever o template renderizado no ficheiro de teste do exercício

Por fim, o resultado do template renderizado é escrito no ficheiro de teste do exercício.

Templates

Os templates são renderizados com a biblioteca hbs, que suporta a sintaxe handlebars (usando a handlebars.java).

Interface de linha de comandos

Há duas formas de executar o gerador de testes:

  1. bin/generate-tests: gera os testes de todos os exercícios que têm um template de gerador
  2. bin/generate-tests <slug>: gera os testes do exercício indicado, se este tiver um template de gerador