Se você possui uma enumeração apenas com valores (nenhum método como se poderia fazer em Java) e essa enumeração faz parte da definição de negócios do sistema, deve-se escrever testes de unidade para isso?
Eu estava pensando que eles deveriam ser escritos, mesmo que pareçam simples e redundantes. Considero que o que diz respeito à especificação de negócios deve ser explicitamente escrito em um teste, seja com unit / integration / ui / etc. testes ou usando o sistema de tipos da linguagem como método de teste. Como os valores que uma enumeração (por exemplo, em Java) deve ter, do ponto de vista dos negócios, não podem ser testados usando o sistema de tipos, acho que deve haver um teste de unidade para isso.
Esta pergunta não é semelhante a esta, pois não trata do mesmo problema que o meu. Nessa pergunta, há uma função comercial (savePeople) e a pessoa está perguntando sobre a implementação interna (forEach). Lá, há uma camada de negócios intermediária (a função salvar pessoas) que encapsula a construção da linguagem (forEach). Aqui, o construto de linguagem (enum) é aquele usado para especificar o comportamento do ponto de vista comercial.
Nesse caso, o detalhe da implementação coincide com a "natureza verdadeira" dos dados, ou seja: um conjunto (no sentido matemático) de valores. É possível usar um conjunto imutável, mas os mesmos valores ainda devem estar presentes lá. Se você usar uma matriz, o mesmo deverá ser feito para testar a lógica de negócios. Eu acho que o enigma aqui é o fato de que a construção da linguagem coincide muito bem com a natureza dos dados. Não sei se me expliquei corretamente
fonte
Respostas:
Não, eles são apenas estado.
Fundamentalmente, o fato de você estar usando uma enumeração é um detalhe de implementação ; esse é o tipo de coisa que você pode querer refatorar em um design diferente.
Enums de teste para completude é análogo ao teste de que todos os números inteiros representáveis estão presentes.
Testar os comportamentos que as enumerações suportam, no entanto, é uma boa ideia. Em outras palavras, se você iniciar a partir de um conjunto de testes aprovado e comentar qualquer valor de enumeração única, pelo menos um teste deverá falhar (os erros de compilação são considerados falhas).
fonte
Hearts
,Spades
,Diamonds
,Clubs
] se você só cartão se um cartão é vermelho / preto?null_ptr
erro. Agora que possui um código de erro via enum. O código que verifica umnull_ptr
erro também consulta o código através da enumeração. Portanto, pode ter um valor de5
(para ex). Agora você precisa adicionar outro código de erro. A enumeração é alterada (digamos que adicionamos uma nova na parte superior da enumeração) O valor denull_ptr
é agora6
. Isso é um problema? agora você retorna um código de erro6
e faz o teste6
. Desde que tudo seja logicamente consistente, você estará bem, apesar dessa mudança ter quebrado seu teste teórico.Você não testa uma declaração enum . Você pode testar se a entrada / saída da função tem os valores de enumeração esperados. Exemplo:
Você não escreve testes verificando, em seguida, enum
Parity
define os nomesEven
eOdd
. Esse teste seria inútil, pois você apenas repetiria o que já é declarado pelo código. Dizer a mesma coisa duas vezes não a torna mais correta.Você fazer testes de escrita verificando
GetParity
digamos retornaráEven
para 0,Odd
para 1 e assim por diante. Isso é valioso porque você não está repetindo o código, está verificando o comportamento do código, independentemente da implementação. Se o código internoGetParity
fosse completamente reescrito, os testes ainda seriam válidos. De fato, os principais benefícios dos testes de unidade são que eles oferecem liberdade para reescrever e refatorar o código com segurança, garantindo que o código ainda funcione conforme o esperado.Mas se você tiver um teste que garanta que uma declaração de enum defina os nomes esperados, qualquer alteração feita no enum no futuro exigirá que você altere também o teste. Isso significa que não é apenas o dobro do trabalho, também significa que qualquer benefício para o teste de unidade é perdido. Se você precisar alterar o código e testar ao mesmo tempo , não há proteção contra a introdução de bugs.
fonte
Se houver um risco de que a alteração da enum interrompa seu código, com certeza, qualquer coisa com o atributo [Flags] em C # seria um bom caso, pois adicionar um valor entre 2 e 4 (3) seria 1 e 2 bit a bit em vez de um item discreto.
É uma camada de proteção.
Você deve ter um código de prática enum com o qual todos os desenvolvedores estejam familiarizados. Não confie nas representações textuais da enumeração comum, mas isso pode entrar em conflito com suas diretrizes de serialização.
Vi pessoas "corrigir" a capitalização de entradas enum, classificá-las em ordem alfabética ou por algum outro agrupamento lógico, que quebrou outros bits do código incorreto.
fonte
Não, um teste que verifica se um enum contém todos os valores válidos e nada mais está basicamente repetindo a declaração do enum. Você só testaria se a linguagem implementa corretamente a construção enum, que é um teste sem sentido.
Dito isto, você deve testar o comportamento que depende dos valores da enumeração. Por exemplo, se você estiver usando os valores da enumeração para serializar entidades para json ou o que quer que seja, ou armazenando os valores em um banco de dados, deverá testar o comportamento de todos os valores da enumeração. Dessa forma, se o enum for modificado, pelo menos um dos testes falhará. De qualquer forma, o que você estaria testando é o comportamento em torno de sua enumeração, não a própria declaração de enumeração.
fonte
Seu código deve estar funcionando corretamente independentemente dos valores reais de uma enumeração. Se for esse o caso, não serão necessários testes de unidade.
Mas você pode ter um código onde a alteração de um valor de enumeração quebrará as coisas. Por exemplo, se um valor de enum for armazenado em um arquivo externo, e após alterar o valor de enum, a leitura do arquivo externo dará o resultado errado. Nesse caso, você terá um comentário GRANDE próximo ao enum alertando qualquer um para não modificar nenhum valor e poderá muito bem escrever um teste de unidade que verifique os valores numéricos.
fonte
Em geral, apenas verificar se uma enumeração possui uma lista de valores embutida não tem muito valor, como disseram outras respostas, porque é necessário atualizar o teste e a enumeração juntos.
Uma vez tive um caso de que um módulo usava tipos de enumerações de dois outros módulos e mapeava entre eles. (Um dos enums tinha lógica adicional, o outro era para acesso ao banco de dados, ambos tinham dependências que deveriam ser isoladas um do outro.)
Nesse caso, adicionei um teste (no módulo de mapeamento) que verificou que todas as entradas de enum na enum de origem também existem na enum de destino (e, portanto, que o mapeamento sempre funcionaria). (Em alguns casos, também verifiquei o contrário.)
Dessa forma, quando alguém adicionava uma entrada de enumeração a uma das enumerações e esquecia de adicionar a entrada correspondente à outra, um teste começava a falhar.
fonte
Enums são simplesmente tipos finitos, com nomes personalizados (espero que sejam significativos). Um enum pode ter apenas um valor, como o
void
que contém apenasnull
(alguns idiomas chamam issounit
e usam o nomevoid
de um enum sem elementos!). Pode ter dois valores, comobool
qual temfalse
etrue
. Pode ter três, comocolourChannel
comred
,green
eblue
. E assim por diante.Se duas enumerações têm o mesmo número de valores, elas são "isomórficas"; ou seja, se mudarmos todos os nomes sistematicamente, podemos usar um no lugar do outro e nosso programa não se comportará de maneira diferente. Em particular, nossos testes não se comportarão de maneira diferente!
Por exemplo,
result
contendowin
/lose
/draw
é isomorfo ao acimacolourChannel
, uma vez que pode substituir por exemplo,colourChannel
comresult
,red
comwin
,green
comlose
eblue
comdraw
, e enquanto fazemos isso em todos os lugares (produtores e consumidores, analisadores e serializadores, entradas de banco de dados, arquivos de log, etc. ), não haverá alterações em nosso programa. Qualquer "colourChannel
teste" que escrevemos ainda será aprovado, mesmo que não existacolourChannel
mais!Além disso, se uma enumeração contiver mais de um valor, sempre podemos reorganizá- los para obter uma nova enumeração com o mesmo número de valores. Como o número de valores não mudou, o novo arranjo é isomórfico ao antigo, e, portanto, poderíamos mudar todos os nomes e nossos testes ainda passariam (observe que não podemos simplesmente mudar a definição; devemos ainda mudar todos os sites de uso também).
O que isso significa é que, no que diz respeito à máquina, enumerações são "nomes distinguíveis" e nada mais . A única coisa que podemos fazer com uma enumeração é ramificar se dois valores são iguais (por exemplo,
red
/red
) ou diferentes (por exemplo,red
/blue
). Portanto, essa é a única coisa que um 'teste de unidade' pode fazer, por exemploComo @ jesm00 diz, esse teste está verificando a implementação da linguagem, e não o seu programa. Esses testes nunca são uma boa idéia: mesmo que você não confie na implementação do idioma, você deve testá-lo de fora , pois não é possível executar os testes corretamente!
Então essa é a teoria; e a prática? O principal problema com essa caracterização das enumerações é que os programas do mundo real raramente são independentes: temos versões herdadas, implantações remotas / incorporadas, dados históricos, backups, bancos de dados ativos etc. para que nunca possamos realmente 'mudar' todas as ocorrências de um nome sem perder alguns usos.
No entanto, essas coisas não são de responsabilidade do próprio enum: alterar um enum pode interromper a comunicação com um sistema remoto, mas, inversamente, podemos resolver esse problema alterando um enum!
Em tais cenários, a enumeração é uma pista falsa: que se um sistema necessita que seja esse caminho, e outro precisa que ele seja de que maneira? Não pode ser os dois, não importa quantos testes escrevamos! O verdadeiro culpado aqui é a interface de entrada / saída, que deve produzir / consumir formatos bem definidos, em vez de "qualquer número inteiro escolhido pela interpretação". Portanto, a solução real é testar as interfaces de E / S : com testes de unidade para verificar se está analisando / imprimindo o formato esperado e com testes de integração para verificar se o formato é realmente aceito pelo outro lado.
Ainda podemos nos perguntar se o enum está sendo "exercitado completamente o suficiente", mas nesse caso o enum é novamente um arenque vermelho. Na verdade, estamos preocupados com o próprio conjunto de testes . Podemos ganhar confiança aqui de duas maneiras:
red
e testamos apenasred
, teremos 100% de cobertura. Um verificador de propriedades (tentará) gerar contra-exemplos para nossas afirmações, como gerar os valoresgreen
eblue
que esquecemos de testar.fonte
Não. Os testes de unidade são para unidades de teste.
https://en.wikipedia.org/wiki/Unit_testing
Um teste automatizado para uma enum declarada estaria testando a integridade do idioma e a plataforma na qual ele está sendo executado, em vez da lógica no código criado pelo desenvolvedor. Seria inútil - a documentação incluída, pois o código que declara a enum serve como documentação, assim como o código que a testaria.
fonte
Você deve testar o comportamento observável do seu código, os efeitos do método / função chama no estado observável. Desde que o código faça a coisa certa, você não precisa testar mais nada.
Você não precisa afirmar explicitamente que um tipo de enum possui as entradas esperadas, assim como não afirma explicitamente que uma classe realmente existe ou que possui os métodos e atributos que você espera.
Na verdade, ao testar o comportamento, você está implicitamente afirmando que as classes, métodos e valores envolvidos no teste existem, portanto, não é necessário explicá-lo explicitamente.
Observe que você não precisa de nomes significativos para que seu código faça a coisa certa; isso é apenas uma conveniência para as pessoas que leem seu código. Você pode fazer seu código funcionar com valores de enumeração como
foo
,bar
... e métodos comofrobnicate()
.fonte