Como testo um leitor de arquivos?

19

Estou trabalhando em um projeto com alguns formatos de arquivo. Alguns formatos são especificados por .xsds, outros pela documentação em seus respectivos sites, e alguns são formatos internos personalizados que não possuem documentação. Mwahahahaha.

Qual é o problema?

Gostaria de testar meus leitores de arquivos, mas não tenho muita certeza de como fazê-lo. O fluxo do aplicativo é assim:

file.___  ===> read by FileReader.java ===> which creates a Model object

onde a FileReaderinterface está

public interface FileReader {
    public Model read(String filename);
}

O Modelpossui vários atributos preenchidos quando o arquivo é lido. Parece algo como

public class Model {
    List<String> as;
    List<String> bs;
    boolean isAPain = true;
    // ...
}

O que eu tentei?

Minha única idéia era criar "geradores" de arquivo para cada formato de arquivo. Esses geradores são basicamente construtores que recebem algumas variáveis ​​(por exemplo, número de comentários a serem gerados em um arquivo) e emitem um arquivo de amostra que, em seguida, leio e comparo o resultado Modelcom as variáveis ​​que usei para gerar o arquivo inicialmente.

Isso tem alguns problemas, no entanto:

  • Os arquivos que ele gera não se parecem com arquivos reais. O gerador não tem nenhuma consciência do contexto.
  • É difícil reconhecer se o gerador gerou casos de borda, pois sou eu quem define manualmente as variáveis. Esse método é pouco melhor do que eu criando uma dúzia de arquivos de amostra.

Existem maneiras melhores de fazer isso?

EDIT: Mudança de unidade para integração, já que é isso que eu realmente quero dizer.

EDIT2: Aqui está um exemplo dos casos extremos que mencionei.

Cada arquivo representa um gráfico composto de vértices e arestas. Esses vértices e arestas podem ser anexados de diferentes maneiras, portanto:

v1 -- e1 --> v2 <-- e2 -- v3

é diferente de

v1 -- e1 --> v2 -- e2 --> v3

em que a direção das bordas é importante. Não tenho certeza se isso está no escopo da pergunta, mas é difícil pensar em todos os casos de arestas pertinentes quando defino manualmente o número de vértices, o número de arestas e apenas giro as conexões aleatoriamente.

sdasdadas
fonte
1
Teste orientado a dados vem à mente. Você pode dar exemplos concretos de casos extremos (com base nos casos extremos que poderiam ser acionados na FileReaderimplementação real )? Exemplo: considerando os casos extremos encontrados nos formatos de arquivo de imagem , para cada entrada da tabela, se a combinação de propriedades de linha / coluna for suportada, deve haver pelo menos um caso de teste (um arquivo de dados) que cubra essa combinação.
Rwong 23/09
@ rwong Adicionei um exemplo, mas não tenho certeza se isso lhe dá uma idéia. Eu acho que meu problema é comum com casos extremos, ou seja. Perdi algum? Embora, o teste orientado a dados pareça interessante. Obrigado!
sdasdadas 23/09
7
Além disso, acabei de perceber isso, mas meus casos extremos literalmente são casos extremos .
sdasdadas 23/09
1
Por que não criar arquivos de teste manualmente e sempre executar contra os mesmos?
Bobson 23/09
@ Bobson Isso é um pouco pior do que usar um gerador. Nesse caso, posso sentir falta de casos extremos (como provavelmente estou sentindo falta agora), mas também posso introduzir erros na digitação. E com arquivos enormes, criá-los por mim mesmo levaria um tempo.
sdasdadas 23/09

Respostas:

19

Primeiro, vamos falar sobre quais são seus objetivos:

  • você obviamente não deseja testar "formatos de arquivo" - deseja testar suas diferentes FileReaderimplementações

  • você deseja encontrar o maior número possível de erros por testes automáticos

Para atingir esse objetivo na íntegra, IMHO você tem que combinar diferentes estratégias:

  • primeiro, teste de unidade real: suas FileReaderimplementações consistirão em muitas partes e funções diferentes. Escreva pequenos testes que testem cada um deles isoladamente; projete suas funções de maneira que elas não precisem realmente ler os dados de um arquivo. Esse tipo de teste ajudará você a testar a maioria dos seus casos extremos.
  • segundo, arquivos gerados: é o que eu chamaria de testes de integração. Esses arquivos ajudarão a rastrear falhas diferentes do ponto 1, por exemplo, combinações de parâmetros específicos, erros no acesso a arquivos etc. Para criar bons casos de teste, também será útil aprender sobre algumas técnicas clássicas, como agrupar casos de teste em classes de equivalência ou teste de valor-limite. Obtenha uma cópia deste livro de Glenford Myers para saber mais sobre isso. O artigo da Wikipedia sobre teste de software também é um bom recurso.
  • terceiro, tente obter dados do mundo real: pode ser difícil verificar se esses arquivos são avaliados corretamente pelos seus FileReaders, mas pode valer a pena fazer isso, pois geralmente encontra bugs não revelados pelas duas primeiras estratégias. Algumas pessoas chamam essas coisas de "testes de integração", outras preferem "testes de aceitação", mas, na verdade, o termo realmente não importa.

IMHO não existe uma abordagem "atalho" que traga o benefício de todas as três estratégias "pelo preço de uma". Se você deseja detectar casos extremos, bem como falhas nos casos padrão e nos casos do mundo real, precisa investir pelo menos algum esforço - provavelmente muito -. Felizmente, todas essas abordagens podem ser usadas para criar testes automáticos e repetíveis.

Além disso, certifique-se de que seus FileReaders não oculte nenhum erro ao ler esses dados - crie verificações / asserções embutidas, lance exceções quando algo der errado internamente, etc. Isso oferece ao seu código de teste uma chance muito melhor de detectar erros , mesmo quando você não possui um arquivo de teste explícito ou um caso de teste para uma situação inesperada.

Doc Brown
fonte
Resposta incrível e editarei o título da minha pergunta para refletir melhor. Obrigado!
sdasdadas 24/09