Como posso escrever o caso de teste de unidade do utilitário de conversão de formato de arquivo?

5

Eu criei um módulo utilitário que converte um formato de arquivo para outro. O arquivo , por exemplo, test.abc , será convertido para , ou seja, test.pqr , e o formato interno dos arquivos será totalmente diferente. Este módulo envolve quase 5 formatos de arquivo diferentes.

Internamente , ele usa uma ferramenta nativa e não tenho nenhum controle sobre ela. Ele converte o arquivo e minha classe de utilitário apenas envia comandos para essa ferramenta e manipula arquivos.

public class Utility {

     public File convertIt(File file, Format to) {
        // Check extension
        // Execute command of native tool accordingly
        // Return resulting file
     }
}

Não consigo concluir como devo escrever casos de teste de unidade para esse utilitário. Como cada formato é diferente e na produção, todos os arquivos serão inseridos pelo usuário. Além disso, existem muitos atributos que são obrigatórios e outros são opcionais. e pode ser possível que um formato de arquivo possa usá-lo ou não.

Atualmente, o que estou pensando é que, em recursos de casos de teste, posso fornecer todos os arquivos de entrada e arquivos resultantes que eu já possuo. Então, posso comparar apenas a saída de cada chamada com o arquivo de saída existente. Mas eu acho que isso não cobrirá todos os cenários e eu posso precisar de mais arquivos para testes.

- resources
       |- input
            |- input1.abc
            |- input2.pqr
            |- input3.xyz
       |- output
            |- output1.xyz
            |- output2.abc
            |- output3.pqr

Minhas perguntas,

  • Esta abordagem está correta?
  • Existe alguma outra abordagem melhor ?
  • Qual é a melhor prática para testar esses métodos que manipulam arquivos?
por CoderCroc 22.08.2016 / 12:12
fonte

3 respostas

3

I want to test my code which is basically a wrapper of native tool.

Perfeito. Se você quisesse testar a ferramenta nativa, você não faria isso através de seu código em nenhum caso. Então você não precisa criar arquivos de entrada ou de saída. Tudo o que você precisa fazer é garantir que a ferramenta nativa seja chamada com os argumentos corretos.

Uma maneira é criar uma classe Executor que possa executar um comando e passá-lo ao seu conversor.

class Converter {
    private Executor executor;

    public Converter(Executor executor) {
        this.executor = executor;
    }

    convertIt() {
        command = ...
        executor.execute(command);
    }
}

}

Em seguida, use Mockito para criar um simulador para teste. Use o junit para facilitar a criação e a execução de métodos de teste.

import org.junit.Test;
import static org.mockito.Mockito.*;

class ConverterTest {
    private Executor executor;

    @Before
    public void setup() {
         executor = mock(Executor.class);
    }

    @Test
    public void TestAtoB() {
        String expectedCommand = ...;
        Converter converter = new Converter(executor);
        converter.convert(...);
        verify(executor).execute(expectedCommand);
    }
}
    
por 22.08.2016 / 22:04
fonte
2

Primeiro de tudo, um ponto pedante. Como esses testes estão chamando um utilitário externo que lê e grava arquivos, esses testes são realmente testes de integração; não testes unitários.

Pelo que parece, para um determinado tipo de arquivo de entrada e tipo de saída escolhido, você fornece um conjunto de parâmetros para o utilitário e esses parâmetros mudam para cada combinação de entrada / saída. Supondo que isso esteja correto, então, para testar adequadamente o método, sua abordagem é boa (por enquanto). Você precisaria criar um arquivo de saída apropriado para cada combinação, o que permitiria que todos os caminhos através do método (e a chamada do utilitário resultante) fossem testados.

Onde a abordagem é menos que ideal é com relação à probabilidade de a utilidade mudar no futuro. Se o arquivo de saída mudar com uma nova versão da ferramenta, seus testes falharão simplesmente porque a ferramenta foi alterada; não porque seu código é falho. Assim você tem um teste frágil. Além disso, uma nova versão deve oferecer mais atributos que melhor convertam os arquivos para seus clientes, mas seus testes não necessariamente selecionam esses novos recursos.

Portanto, você provavelmente precisará de um fluxo de trabalho tratando os testes como suspeitos, regenerando os arquivos de saída e verificando as alterações de atributos sempre que uma nova versão do utilitário for liberada. Se você colocar isso em prática, então esta abordagem de teste deve servir bem a você.

    
por 22.08.2016 / 14:10
fonte
1

Apesar do seu próprio comentário, acho que o OP faz querer testar o conversor subjacente implicitamente.

Por quê? Um teste unitário para um wrapper é quase inútil (exceto que é muito complexo, mas deve ser dividido em partes menores e menos complexas). Você só pode testar se você faz a chamada para a biblioteca subjacente corretamente, e os argumentos são passados corretamente. Mas você reconhecerá que dentro dos primeiros testes manuais.

O que é realmente interessante é se o lib se comporta como esperado, especialmente para casos de canto (por exemplo, .abc não define um parâmetro que é obrigatório para .xyz). E se a lib ainda tiver o mesmo comportamento, ao atualizar para uma versão mais nova.

No final, sua abordagem é boa, apenas duas notas:

  • tente testar apenas alguns casos padrão (testes de fumaça), mas muitos casos especiais interessantes
  • Eu usaria outra estrutura para os arquivos de recursos (acho que é mais útil, mas é uma questão de gosto): resources / abc para xyz / missing params / input.abc, expected.xyz
por 23.08.2016 / 20:46
fonte