quarta-feira, 15 de maio de 2013

Gerador de Casos de Teste

Um dos grandes desafios envolvidos em resolver um exercício da maratona de programação é pensar em um caso de teste onde seu programa vai falhar.
Os casos de teste oferecidos na descrição do exercício geralmente cobrem a parte mais simples e superficial do mesmo, mas quando chega a hora de submeter o código, ele deve passar por casos de testes gigantescos e complexos, os quais você nem de longe tratou.

Nesse post vou dar um breve exemplo de como criar um gerador de casos de teste, o qual pode lhe ajudar a testar o programa e verificar por si mesmo em quais casos seu programa está falhando.

Aqui está o código que eu montei para exemplificar esse post:
https://github.com/crbonilha/codes/blob/master/Exemplo%20Gerador%20Casos%20de%20Teste

(Linha 6 do código):
Caso esteja programando na linguagem C ou C++ (meu caso), será necessário utilizar alguns metodos responsáveis por manipular arquivos externos, tais como arquivos .txt, ou arquivos sem extensão alguma, mas que contenham nele apenas valores que serão usados no seu programa.
Esses metodos manipulam variáveis do tipo FILE, que serão responsáveis por representar seu arquivo externo. Quem ainda não tem muita familiaridade com essa abordagem, procure estudar algo na internet, em especial o método "fopen()" e "fprintf()", que, para o nosso caso, é mais do que o suficiente.

Voltando ao contexto da maratona, para que você pense em como gerar um caso de teste, primeiro você tem que entender a "hierarquia" de cada caso de teste, por exemplo, no exercicio Bilhetes Falsos (http://www.urionlinejudge.com.br/judge/problems/view/1318), cada caso de teste contém dois inteiros, N e M, e logo após, M inteiros. Seu gerador será responsável por gerar os dois inteiros iniciais (N e M), e logo após, M inteiros. Sim, é bobagem, mas é importante (Linhas 15 e 21).
Outro detalhe que pode passar em branco é que dentre todos os M valores gerados, todos devem estar no intervalo de 1 a N, portanto cuidado na hora de chamar o método de valores aleatórios (Linha 19).

Eu costumo deixar a parte do N e M por minha conta (Linha 13), assim eu decido se quero um caso de teste grande ou pequeno, porém esses mesmos valores poderiam facilmente serem gerados aleatoriamente, como os outros.

Ok, após todos os valores gerados, basta adaptar seu programa que resolve o exercício para ler as entradas do arquivo de teste que você gerou, em vez de ler da entrada padrão como estamos acostumados. Para isso estudem o método "fscanf()".

Agora é possível criar milhares de casos de teste e fazer seu programa rodar todos em segundos. A última parte é saber identificar, dentre milhares de saidas, qual está errada. Restam-lhe duas alternativas: na internet é possivel encontrar os casos de teste de entrada e suas saidas utilizados nas maratonas anteriores, portanto basta encontrá-los e compará-los ao teu; o site com juiz online do URI tem uma ferramenta chamada toolkit, e com ele é possível entregar um caso de teste gerado por você e verificar qual seria a saída de um programa que está funcionando corretamente.

Obviamente, ambas as formas de comparar a saida com algum recurso da internet não lhe será útil na hora da maratona, porém bugs nos quais o seu programa aparentemente para de funcionar, ou estoura o tempo limite, podem ser visivelmente notados com esse tipo de abordagem.

A ferramenta está aí, basta saber quando e como usá-la...

Nenhum comentário:

Postar um comentário