Codecoverage vs ExpectedException
-
05-07-2019 - |
Pergunta
Eu tenho vários UnitTests deste padrão:
[TestMethod ()]
[ExpectedException (typeof (ArgumentNullException))]
public void DoStuffTest_Exception ()
{
var foo = new Foo ();
Foo.DoStuff (null);
}
Acontece que markes de cobertura de código a linha de lançamento como meia-run, assim que eu conseguir um bloco de código descoberto cada vez.
Depois de pensar sobre este problema por um tempo, a melhor solução que eu poderia vir com foi a adição de um try / catch. Uma vez que este é um padrão repetido, eu vou para criar um método auxiliar ao longo das linhas
public static void ExpectException<_T> (Action action) where _T: Exception
{
try { action(); }
catch (_T) { return; }
Assert.Fail ("Expected " + _T);
}
Isso teria o benefício lateral agradável que eu poderia adicionar todos os testes de exceção para os testes não-jogando.
É este um projeto válido, ou eu perdi alguma coisa?
Editar:. Ugs ... parece que as folhas método ExpectException acima de mim com um bloco descoberto assim
Solução
O que você está sugerindo é válido. Além de você problema de cobertura de código, eu diria que é melhor do que usar o atributo ExpectedException
como explicitamente mostra que se espera linha do teste para lançar a exceção. Usando meios ExpectedException
que qualquer linha de código no teste pode jogar o tipo de exceção que o esperado e o teste ainda vai passar. Se se origina o erro de outra chamada que não era esperado para jogar, ele pode disfarçar o fato de que o teste deve estar falhando porque a linha que deve estar jogando não é.
O que seria uma modificação útil para o que você tem proposto seria para retornar a exceção capturada:
public static _T ExpectException<_T> (Action action) where _T: Exception
{
try { action(); }
catch (_T ex) { return ex; }
Assert.Fail ("Expected " + typeof(_T));
return null;
}
Isto permitiria o código de teste de mais afirmar a excepção se desejado (isto é. Para verificar uma mensagem em particular foi utilizado).
NUnit (apesar de não parecer que você está usando-o como você tem um atributo TestMethod
) tem um built-in construção semelhante ao que você propôs:
Assert.Throws<ArgumentNullException>(() => Foo.DoStuff(null))
Outras dicas
@adrianbanks o ExpectException não funciona como esperado se o parâmetro de ação joga outra exceção do que a exceção esperado:
[TestMethod]
public void my_test()
{
ExpectException<InvalidOperationException>(delegate()
{
throw new ArgumentException("hello");
});
}
Quando eu executar o TestMethod "my_test" Eu só tenho uma mensagem dizendo que o método de ensaio levantada e System.ArgumentException: Olá. Neste caso, deve diz "esperar InvalidOperationException". Proponho uma nova versão para o método ExpectException:
public static void VerifierException<T>(Action action) where T : Exception
{
try
{
action();
}
catch (Exception ex)
{
Assert.IsInstanceOfType(ex, typeof(T));
return;
}
Assert.Fail("Aucune exception n'a été déclenchée alors qu'une exception du type " + typeof(T).FullName + " était attendue");
}
Eu sei que este é um tema antigo, mas eu corri para o mesmo problema.
Eventualmente, eu me questionava: por que eu preciso de saber a cobertura dos testes? Eu não - Então, vamos erradicá-los, de modo que a cobertura é mais limpo
. No meu projeto de teste eu adicionei um arquivo CodeCoverage.runsettings
e este é o conteúdo:
<?xml version="1.0" encoding="utf-8" ?>
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Configuration>
<CodeCoverage>
<ModulePaths>
<Exclude>
<ModulePath>.*tests.dll</ModulePath>
<ModulePath>.*Tests.dll</ModulePath>
<!-- Add more ModulePath nodes here. -->
</Exclude>
</ModulePaths>
</CodeCoverage>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>
Depois de seleccionar esta Configurações de teste arquivo minha cobertura de código é 100%
Desta forma, não há necessidade de 'cortar' o sistema de cobertura de código de teste de unidade, apenas para atingir 100%: -)
Yep isso é bastante tarifa normal - um monte de nossos testes de fazer o mesmo. Ao mesmo tempo, você tem que saber se você não está colocando muito alto um valor de cobertura de código se essas meias-ramos pesar muito para que valha a pena o esforço.