Eu tenho algo parecido com isto:
public byte[] EncodeMyObject(MyObject obj)
Eu tenho testado em unidade assim:
byte[] expectedResults = new byte[3]{ 0x01, 0x02, 0xFF };
Assert.IsEqual(expectedResults, EncodeMyObject(myObject));
EDIT: As duas maneiras que eu vi propostas são:
1) Usando valores esperados codificados, como no exemplo acima.
2) Usando um decodificador para decodificar a matriz de bytes codificados e comparando os objetos de entrada / saída.
O problema que vejo no método 1 é que ele é muito quebradiço e requer muitos valores codificados.
O problema com o método 2 é que o teste do codificador depende do funcionamento correto do decodificador. Se o codificador / decodificador for quebrado igualmente (no mesmo local), os testes poderão produzir falsos positivos.
Essas podem muito bem ser as únicas maneiras de testar esse tipo de método. Se for esse o caso, tudo bem. Estou fazendo a pergunta para ver se existem estratégias melhores para esse tipo de teste. Não consigo revelar as partes internas do codificador específico em que estou trabalhando. Em geral, estou perguntando como você resolveria esse tipo de problema e não acho que os internos sejam importantes. Suponha que um determinado objeto de entrada sempre produza a mesma matriz de bytes de saída.
fonte
myObject
vai demyObject
para{ 0x01, 0x02, 0xFF }
? Esse algoritmo pode ser dividido e testado? A razão pela qual pergunto é atualmente, parece que você tem um teste que prova que uma coisa mágica produz outra coisa mágica. Sua única confiança é que a única entrada produz a única saída. Se você pode quebrar o algoritmo, pode ganhar mais confiança no algoritmo e ser menos dependente de entradas e saídas mágicas.Respostas:
Você está em uma situação um pouco desagradável lá. Se você tivesse um formato estático no qual estava codificando, seu primeiro método seria o caminho a seguir. Se fosse apenas o seu próprio formato, e ninguém mais tivesse que decodificar, o segundo método seria o caminho a seguir. Mas você realmente não se encaixa em nenhuma dessas categorias.
O que eu faria é tentar dividir as coisas pelo nível de abstração.
Então, eu começaria com algo no nível de bits, que testaria algo como
Portanto, a idéia é que o bitwriter saiba como escrever os tipos mais primitivos de campos, como ints.
Tipos mais complexos seriam implementados usando e testados algo como:
Observe que isso evita qualquer conhecimento de como os bits reais são compactados. Isso foi testado pelo teste anterior e, para esse teste, vamos assumir que ele funciona.
Então, no próximo nível de abstração, teríamos
então, novamente, não tentamos incluir o conhecimento de como as sequências de caracteres, datas ou números são realmente codificados. Neste teste, estamos interessados apenas na codificação produzida por encodeObject.
O resultado final é que, se o formato das datas for alterado, você precisará corrigir os testes que realmente envolvem datas, mas todos os outros códigos e testes não se preocupam com a forma como as datas são realmente codificadas e depois de atualizar o código para criar Nesse trabalho, todos esses testes serão aprovados.
fonte
Depende. Se a codificação for algo completamente fixo, em que toda implementação deve criar exatamente a mesma saída, não faz sentido verificar nada além de verificar se as entradas de exemplo são mapeadas exatamente para as saídas esperadas. Esse é o teste mais óbvio e provavelmente também o mais fácil de escrever.
Se houver espaço de manobra com saídas alternativas, como no padrão MPEG (por exemplo, existem certos operadores que você pode aplicar à entrada, mas você pode negociar o esforço de codificação versus a qualidade da saída ou o espaço de armazenamento), é melhor aplicar o definiu a estratégia de decodificação para a saída e verifique se é a mesma da entrada - ou, se a codificação estiver com perdas, está razoavelmente próxima da entrada original. Isso é mais difícil de programar, mas protege você contra futuras melhorias que possam ser feitas no seu codificador.
fonte
Teste isso
encode(decode(coded_value)) == coded_value
edecode(encode(value)) == value
. Você pode fornecer uma entrada aleatória para os testes, se desejar.Ainda é possível que o codificador e o decodificador sejam quebrados de maneiras complementares, mas isso parece bastante improvável, a menos que você tenha um entendimento conceitual do padrão de codificação. Fazer testes codificados e codificados (como você já está fazendo) deve se proteger contra isso.
Se você tiver acesso a outra implementação disso que funcione, pelo menos você poderá usá-la para ter certeza de que sua implementação é boa, mesmo que seja impossível usá-la nos testes de unidade.
fonte
decode(encode(char))
não seria igualchar
(seria igualchar+2
).Teste com os requisitos .
Se os requisitos forem apenas 'codificar para um fluxo de bytes que, quando decodificado, produz um objeto equivalente'., Basta testar o codificador decodificando. Se você estiver escrevendo o codificador e o decodificador, basta testá-los juntos. Eles não podem ter "erros de correspondência". Se eles trabalharem juntos, o teste será aprovado.
Se houver outros requisitos para o fluxo de dados, você precisará testá-los examinando os dados codificados.
Se o formato codificado for predefinido, você deverá verificar os dados codificados com relação ao resultado esperado, como fez, ou (melhor) obter um decodificador de referência confiável para fazer a verificação. O uso de um decodificador de referência elimina a possibilidade de você ter interpretado mal a especificação de formato.
fonte
Dependendo da estrutura e do paradigma de teste que você está usando, você ainda pode usar o padrão Dispor Lei de Disposição para isso, como você disse.
Você deve conhecer os requisitos
EncodeMyObject()
e pode usar esse padrão para testar contra cada um deles critérios válidos e inválidos, organizando cada um deles e codificando o resultado esperado paraexpected
, da mesma forma para o decodificador.Como o esperado é codificado, eles serão frágeis se você tiver uma mudança maciça.
Você pode automatizar com algo orientado a parâmetros (dê uma olhada no Pex ) ou, se estiver fazendo DDD ou BDD, dê uma olhada no gerkin / pepino .
fonte
Você decide o que é importante para você.
É importante para você que um Objeto sobreviva à ida e volta e o formato exato da ligação não seja realmente importante? Ou o formato exato do fio é uma parte importante da funcionalidade do seu codificador e decodificador?
Se for o primeiro, certifique-se de que os objetos sobrevivam à ida e volta. Se o codificador e o decodificador estiverem quebrados de maneiras exatamente complementares, você realmente não se importa.
Neste último caso, você precisa testar se o formato do fio é o esperado para as entradas fornecidas. Isso significa testar o formato diretamente ou usar uma implementação de referência. Mas, depois de testar o básico, você pode obter valor de testes adicionais de ida e volta, que devem ser mais fáceis de escrever em volume.
fonte