Desenvolvimento Orientado a Testes: Uma maneira boa / aceita de testar as operações do sistema de arquivos?


14

No momento, estou trabalhando em um projeto que gera uma tabela (entre outras coisas) com base no conteúdo de um sistema de arquivos e, por sua vez, faz algumas modificações de metadados nas coisas que encontra. A questão é: como os testes devem ser escritos em torno disso ou configurados? Existe uma maneira fácil de zombar disso? Ou devo configurar uma "caixa de areia"?

Respostas:


13

Como você sempre faz no TDD com recursos externos: você cria uma ou mais interfaces para as operações do sistema de arquivos e "zomba delas". Você deseja testar seu "gerador de tabelas" e seu código de modificação de metadados, não as operações do sistema de arquivos (provavelmente você está usando implementações de bibliotecas prontas para acessar o sistema de arquivos).


O TDD não recomenda zombar da implementação da unidade em teste. Veja (e, g) solnic.eu/2014/05/22/mocking-and-ruby.html
soru

1
@soru: Não é isso que esta resposta recomenda. Ele recomenda primeiro criar interfaces e depois zombar da interface . Então você testa a lógica de negócios, mas não a interface do sistema de arquivos.
sleske

5
Mas parece que a lógica de negócios é definida em termos de arquivos e diretórios. Portanto, o que chama a API do sistema de arquivos é o que precisa ser testado. O teste de qualquer lógica comercial não relacionada a arquivos não precisa de zombaria; apenas teste.
soru 9/04/2015

@soru, então você cria uma camada fina em torno de arquivos e pastas com uma interface definida de forma que todas as operações específicas do domínio estejam do lado do cliente, e o lado da implementação é trivial o suficiente para ter certeza de que funciona sem teste de unidade (os testes de integração serão ainda é necessário). Semelhante à idéia de um Humble Dialog no código da interface do usuário, ou usando um Repositório simulado no código que opera em objetos persistentes.
Jules

2
Com tanta eficiência, renunciamos ao teste da classe real que interage com o sistema de arquivos, banco de dados, etc. porque acreditamos que não podemos testá-lo por unidade e devemos fazer testes de integração para testá-lo. Isso está correto?
Andrew Savinykh

11

O que há de errado em ter um sistema de arquivos "teste"?

Crie uma pasta de modelo / estrutura de diretório que tenha conteúdo suficiente para testar suas operações.

Durante a configuração do seu teste de unidade, copie esta estrutura inicial (recomendamos que você ZIP o modelo e descompacte na área de teste). Execute seus testes. Exclua tudo durante o desmonte.

O problema da zombaria é, em primeiro lugar, sistemas de arquivos, sistemas operacionais e bancos de dados que pertencem ao seu projeto, na verdade, não se qualificam como recursos externos e, em segundo lugar, zombar de chamadas de sistema de baixo nível é demorado e propenso a erros.


5
A zombaria das operações do sistema de arquivos criará testes de execução muito mais rápidos do que o uso de um sistema de arquivos real e, se isso for mais "suscetível a erros", é discutível, eu diria que depende da implementação. No entanto, acho que sua sugestão é boa para criar testes de integração automatizados (o que normalmente eu faria primeiro quando não fazia TDD). Mas o OP pediu oficialmente TDD, e os testes de unidade TDD precisam ser rápidos.
Doc Brown

1
Eu acho que os sistemas de arquivos, se ridicularizados, deveriam ter uma API inteira escrita e mantida por algum grupo, porque você está reinventando a roda, se fizer algo significativo com o sistema de arquivos.
Frank Hileman

2
@ Doc Brown - Estou supondo que ele quer fazer dir, excluir e renomear operações de tipo, todas com casos extremos que seriam dolorosos de zombar. Também no hardware moderno, descompactar alguns arquivos pequenos em um diretório é apenas um pouco mais lento do que carregar uma classe Java - afinal, é tudo E / S.
James Anderson

Quanto mais eu penso sobre o sistema de arquivos de teste, mais eu gosto.
91115 Frank Hileman

3

Esse é o tipo de coisa que você definitivamente precisa para testar a integração, pois os sistemas de arquivos do mundo real têm todo tipo de comportamento estranho (como a maneira como o Windows não permite excluir um arquivo se algum processo, incluindo o deleter, o abrir).

Portanto, a abordagem do TDD é escrever primeiro o teste de integração (o TDD, estritamente falando, não possui conceitos distintos de 'teste de unidade' e 'teste de integração'; são apenas testes). Muito provavelmente isso será suficiente; então trabalho feito, pare, vá para casa .

Caso contrário, haverá alguma complexidade interna que não será fácil de testar adequadamente organizando arquivos. Nesse caso, você simplesmente elimina essa complexidade, coloca-a em uma classe e escreve testes de unidade para essa classe . Muito provavelmente, você descobrirá que essa classe comum também é utilizável nos casos de banco de dados, arquivo xml etc.

Em nenhum caso você pegaria o núcleo fundamental do código que está escrevendo e o "zombaria" para escrever testes que serão aprovados se a unidade em teste estiver ou não errada.


Essa resposta realmente colocou em perspectiva para mim - 'unit test' and 'integration test'; they are just tests.acho que, realisticamente, essa será a melhor solução para o meu caso - eu realmente preciso testar as bibliotecas do sistema de arquivos que estou usando para casos extremos e como o aplicativo deve responder. Essa. Se eu mudar para uma biblioteca diferente do sistema de arquivos, não quero reescrever um monte de códigos de simulação / teste para trabalhar com a nova biblioteca, mas ter uma estrutura de pastas de teste e testes de integração tornaria isso muito mais simples.
tehDorf

2

Entendo sua pergunta como "Uma maneira boa / aceita de testar uma classe que depende das operações do sistema de arquivos". Não presumo que você queira testar o sistema de arquivos do seu sistema operacional.

Para manter o esforço de 'fazer interface com as operações do sistema de arquivos e "zombar delas' ', como a resposta do @Doc Brown sugerida o menor possível, é uma boa ideia usar fluxos binários java ou leitor de texto (ou equivalente em c # ou a linguagem de programação que você está usando) em vez de usar Arquivos com nomes de arquivos diretamente na sua classe desenvolvida por tdd.

Exemplo:

Usando java, eu implementei uma classe CsvReader

public class CsvReader {
    private Reader reader;

    public CsvReader(Reader reader) {
        this.reader = reader;
    }
}

Para testar, usei dados de memória como este

String contentOfCsv = "TestColumn1;TestColumn2\n"+
    "value1;value2\n";

CsvReader sut = new CsvReader(java.io.StringReader(contentOfCsv));

ou incorporar dados de teste nos recursos

CsvReader sut = new CsvReader(getClass().getResourceAsStream("/data.csv"));

Na produção, eu uso o sistema de arquivos

CsvReader sut = new CsvReader(new BufferedReader( new FileReader( "/import/Prices.csv" ) ));

Dessa forma, meu CsvReader não depende do sistema de arquivos, mas de uma abstração "Reader", onde há uma implementação para o sistema de arquivos.


2
O único problema aqui é que o OP não estava falando de operações de arquivo, mas de operações de sistema de arquivos e operações de metadados - acho que ele quis dizer algo como listar todos os arquivos em um diretório, atualizar algumas informações EXIF ​​em todos os arquivos de imagem etc.
Doc Brown

Isto está certo.
Kirbinator

1
Você pode criar IDirectoryLister que possui um método String [] List (diretório de String); o FakeDirectoryLister pode implementar esse método retornando apenas a nova String [] {".", "..", "foo.bat", "bar.exe"};
Anders Lindén

0

Crie um wrapper para as operações do sistema de arquivos. Nos testes, passe uma simulação que implemente a mesma interface que o wrapper. Na produção, passe no invólucro.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.