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

Foi útil?

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.

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