Pergunta

Às vezes eu vêm em um teste de unidade que não afirma nada. O exemplo particular me deparei esta manhã estava testando que um arquivo de log foi escrito para quando uma condição foi cumprida. A suposição era de que, se nenhum erro foi jogado o teste passou.

Eu pessoalmente não tenho um problema com isso, no entanto, parece ser um pouco de um "cheiro de código" para escrever um teste de unidade que não tem nenhum afirmações associadas com ele.

Apenas querendo saber o que a opinião das pessoas sobre isso são?

Foi útil?

Solução

Esta seria a maneira oficial de fazê-lo:

// Act
Exception ex = Record.Exception(() => someCode());

// Assert
Assert.Null(ex);

Outras dicas

É simplesmente um teste muito mínima, e deve ser documentado como tal. Ele apenas verifica se ele não explode quando executado. A pior parte sobre testes como este é que eles apresentam uma falsa sensação de segurança. Sua cobertura de código vai subir, mas é ilusório. Muito mau odor.

Se não houver nenhuma afirmação, não é um teste.

Parado ser preguiçoso -. Pode demorar um pouco de tempo para descobrir como obter a afirmação de lá, mas vale a pena saber que fiz o que você espera que ele faça

Estes são conhecidos como testes de fumaça e são comuns. Eles são verificações básicas de sanidade. Mas eles não devem ser os únicos tipos de testes que você tem. Você ainda precisa de algum tipo de verificação em outro teste.

teste Tal cheiros. Ele deve verificar se o arquivo foi escrito para, pelo menos, que o tempo modificado foi atualizado talvez.

Eu vi algumas provas escritas desta forma que acabou por não testar nada ou seja, o código não funcionou, mas não explodiu também.

Se você tem alguma exigência explícita de que o código sob teste não lançar uma exceção e você quer chamar explicitamente este fato (testes como requisitos docs), então eu faria algo assim:

try
{
  unitUnderTest.DoWork()
}
catch
{
  Assert.Fail("code should never throw exceptions but failed with ...")
}

... mas isso ainda cheira um pouco para mim, provavelmente porque ele está tentando provar uma negativa.

Em certo sentido, você está fazendo uma afirmação implícita - de que o código não lançar uma exceção. Claro que seria mais valioso para realmente pegar o arquivo e encontrar a linha apropriada, mas acho que alguma coisa é melhor que nada.

Em geral, eu vejo isso ocorrendo em testes de integração, apenas o fato de que algo sucedeu a conclusão é bom o suficiente. Neste caso Im bem com isso.

Eu acho que se eu vi uma e outra vez no testes de unidade eu seria curioso para saber como útil os testes realmente eram.

EDIT:. No exemplo dado pelo OP, existe algum resultado testável (resultado logfile), assumindo assim que se nenhum erro foi jogado que ele trabalhou é preguiçoso

Pode ser uma solução pragmática bom, especialmente se a alternativa é nenhum teste em tudo.

O problema é que o teste iria passar se todas as funções chamadas havia-ops. Mas às vezes ele simplesmente não é viável para verificar os efeitos colaterais são o que você esperava. No mundo ideal haveria tempo suficiente para escrever os cheques para todos os testes ... mas eu não vivo lá.

O outro lugar que eu usei esse padrão é para a incorporação de alguns testes de desempenho com testes de unidade, porque essa era uma maneira fácil de fazê-los correr cada compilação. Os testes não afirmam nada, mas medir quanto tempo o teste teve e log isso.

Eu vi algo assim antes e acho que isso foi feito apenas para sustentar números de cobertura de código. Provavelmente não é realmente testar o comportamento código. Em qualquer caso, concordo que ele (a intenção) deve ser documentada no teste para maior clareza.

O nome do teste deve documentar isso.

void TestLogDoesNotThrowException(void) {
    log("blah blah");
}

Como o teste de verificar se o log é escrito sem afirmação?

Eu tenho que admitir que eu nunca escrevi um teste de unidade que verificou que estava registrando corretamente. Mas eu pensei sobre isso e me deparei com essa discussão de como isso poderia ser feito com JUnit e Log4J. A sua não é muito bonito, mas parece que ele iria trabalhar.

Os testes devem sempre assert algo, caso contrário, o que você está provando e como você pode sempre reproduzir evidência de que suas obras de código?

Nós fazemos isso o tempo todo. Nós zombar nossas dependências usando JMock, então eu acho que em certo sentido, o quadro JMock está fazendo a afirmação para nós ... mas é algo como isto. Temos um controlador que queremos teste:

Class Controller {
  private Validator validator;

  public void control(){
    validator.validate;
  }

  public setValidator(Validator validator){ this.validator = validator; }
}

Agora, quando testamos Controlador nós não' quer testar Validador porque ele tem suas próprias provas. por isso temos um teste com JMock apenas para se certificar que chamamos de validação:

public void testControlShouldCallValidate(){
  mockValidator.expects(once()).method("validate");
  controller.control;
}

E isso é tudo, não há nenhuma "afirmação" para ver, mas quando você chamar o controle e o método de "validar" não é chamado em seguida, o quadro JMock você joga uma exceção (algo como "método de espera não invocou" ou algo assim).

Temos aqueles em todo o lugar. É um pouco para trás desde que você basicamente configurar sua afirmação em seguida, fazer a chamada para o método testado.

Às vezes eu usar minha unidade testar framework de escolha (NUnit) para métodos de construção que funcionam como pontos de entrada para partes específicas do meu código. Estes métodos são úteis para a criação de perfil de desempenho, consumo de memória e consumo de recursos de um subconjunto do código.

Estes métodos são definitivamente não testes de unidade (mesmo que estejam marcados com o atributo [Test]) e são sempre sinalizadas para ser ignorado e explicitamente documentados quando são verificados no controle de origem.

Eu também uso ocasionalmente estes métodos como pontos de entrada para o depurador Visual Studio. Eu uso ReSharper a passo diretamente para o teste e depois para o código que eu quero depuração. Estes métodos ou não torná-lo tão longe como controle de origem, ou eles adquirem o seu próprio afirma.

Os meus testes de unidade "reais" são construídos durante os ciclos TDD normais, e eles sempre assert algo, embora nem sempre diretamente - às vezes as afirmações fazem parte do quadro de zombaria, e às vezes eu sou capaz de refatorar afirmações semelhantes em um único método. Os nomes desses métodos reformulado sempre começar com o prefixo "Assert" para torná-lo óbvio para mim.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top