Conteúdos da cadeira

Propriedades e testes com QuickCheck

Propriedades em vez de exemplos, geradores automáticos e leitura de contraexemplos.

Markdown

Perguntar sobre esta página

ChatGPTClaudePerplexityGeminiCopiar e abrir

Envia o link e pede à IA para ler a página. No Gemini, cola a pergunta copiada.

Ver pergunta para copiar
Nesta página

Um teste de exemplo verifica um caso: reverse [1,2,3][3,2,1]. Uma propriedade afirma uma lei para todos os casos: inverter duas vezes devolve a lista original. O QuickCheck testa a propriedade em centenas de casos aleatórios por ti. Em vez de inventares exemplos, inventas leis, e a ferramenta trata de as tentar partir.

A primeira propriedade

Propriedades são funções que devolvem Bool, com tipos concretos para a ferramenta saber o que gerar:

import Test.QuickCheck

prop_revRev :: [Int] -> Bool
prop_revRev xs = reverse (reverse xs) == xs

No GHCi, com o pacote QuickCheck instalado:

ghci> quickCheck prop_revRev
+++ OK, passed 100 tests.

A ferramenta gerou 100 listas aleatórias (vazias, curtas, longas, com negativos e repetidos) e a igualdade valeu em todas. Repara no que isto compra: um teste de exemplo cobre a lista que escreveste; a propriedade cobre as listas que nunca te lembrarias de escrever, incluindo [], que apanha metade dos erros de recursão.

Quando falha: o contraexemplo

Uma propriedade falsa dá um contraexemplo mínimo. Afirma que ordenar é a identidade:

import Data.List (sort)

prop_sortId :: [Int] -> Bool
prop_sortId xs = sort xs == xs
ghci> quickCheck prop_sortId
*** Failed! Falsifiable (after 3 tests):
[1,0]

O QuickCheck responde que a propriedade é falsificável e mostra a testemunha: [1,0], já encolhida (shrinking) de um caso aleatório maior até ao mínimo que ainda falha. O número de testes varia de corrida para corrida; a lista curta fora de ordem é o essencial. O fluxo de trabalho é este: escreve a propriedade, vê-a falhar, lê o contraexemplo, corrige a ideia. A versão verdadeira compara duas ordenações:

prop_sortSort :: [Int] -> Bool
prop_sortSort xs = sort (sort xs) == sort xs
ghci> quickCheck prop_sortSort
+++ OK, passed 100 tests.

Geradores e condições

Por omissão, o QuickCheck gera valores arbitrários do tipo pedido: inteiros pequenos e grandes, listas de vários tamanhos, carateres Unicode. Quando a propriedade só faz sentido sob uma condição, impõe-na com ==>:

prop_divMod :: Int -> Int -> Property
prop_divMod x y = y /= 0 ==> (x `div` y) * y + (x `mod` y) == x

Os casos com y == 0 são descartados antes de contar. Se a condição for demasiado rara, a ferramenta avisa que não conseguiu casos suficientes, e aí o remédio é um gerador à medida com forAll. Para esta cadeira, chega saberes que o gerador existe e que a seta ==> filtra.

Ver o ficheiro no GitHub

À tua maneira

Escolhe como preferes ler.

Aparência
Ajustar cores e largura
Cor de destaque do tema FEUP
Tipo de letra

Álgebra, lógica e uma ideia de cada vez.

As tuas escolhas ficam guardadas neste navegador.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.