Ainda devo usar o Debug.Assert hoje?

23

Recentemente, deparei com um código recém-escrito que foi intercalado com muito Debug.Assert (C #).

Ainda devemos usar isso amplamente, apesar do uso de TDD, BDD e testes de unidade em geral?

Dominik Fretz
fonte
9
Não vejo como um exclui o outro.
SuperM
2
@superM Eu definitivamente vi desenvolvedores preguiçosos adicionarem testes como afirmações antes, pois eles escreveram seu código de modo que era difícil zombar de dependências. escusado será dizer que eu não recomendaria isso
jk.

Respostas:

23

Não vejo nenhuma razão para você não usar o Assert. Ao fazer isso, você já reconheceu a necessidade de proteções, como pré-condições e invariantes, e está fazendo uma mudança em direção ao Design por contrato . Afirmar é apenas uma maneira de conseguir isso ...

// Precondition using Asert
void SomeMethod(Foo someParameter)
{
    Debug.Assert(someParameter != null)
}

// Precondition using If-Then-Throw
void SomeMethod(Foo someParameter)
{
    if (someParameter == null)
        throw new ArgumentNullException("someParameter");
}

// Precondition using Code Contracts
void SomeMethod(Foo someParameter)
{
    Contract.Requires(someParameter != null);
}

// Precondition using some custom library
void SomeMethod(Foo someParameter)
{
    Require.ArgumentNotNull(() => someParameter);
}

Todas são maneiras de conseguir a mesma coisa: robustez no código. Tudo se resume a escolher uma opção, da qual Assert é uma opção válida.

Observe que até agora não mencionei testes de unidade, pois eles realizam algo muito diferente. Um teste de unidade prova formalmente a robustez do código exercitando uma proteção:

[Test]
void SomeMethod_WhenGivenNull_ThrowsArgumentNullException()
{
    delegate call = () => someObject.SomeMethod(null);

    Assert.That(call).Throws<ArgumentNullException>();
}

Este é um tipo totalmente diferente de afirmar ...

** Observe que, em algumas estruturas, é realmente muito difícil testar a unidade para uma falha de asserção, pois uma falha de asserção pode reduzir o tempo de execução inteiro, portanto, uma das outras opções pode ser preferida ... *

MattDavey
fonte
10

Considero afirmações e testes de unidade como duas ferramentas diferentes na minha caixa de ferramentas. Algumas coisas são mais adequadas para uma e outras são mais adequadas para a outra.

Como exemplo, hoje em dia eu uso principalmente declarações para validar parâmetros para métodos não públicos.

vaughandroid
fonte
5

Eu vejo Debug.Assert como otimização prematura hoje em dia. A menos que você realmente precise do desempenho, suprimir o Assert no modo de liberação pode ocultar bugs por mais tempo.

Como MattDavey salienta, os contratos de código podem ser superiores, fornecendo verificação estática em vez de verificação dinâmica e, se não estiver disponível, eu preferiria o Trace.Assert ou uma planilha antiga.if(x) throw SomeException;

jk.
fonte
4
Vale ressaltar que a geração de código com o Visual Studio no modo de lançamento fará com que todas as chamadas para métodos da Debugclasse sejam ignoradas da compilação ... portanto, suprimir as chamadas Assertsimplesmente para desempenho não é apenas otimização prematura, é um absurdo.
precisa saber é o seguinte
@ Konamiman esse é o ponto, eu quase sempre quero que falhe da mesma maneira no modo de lançamento:. Debug.Assert não serve para mim 97% do tempo
jk.
O que são esses 3%, @jk? Apenas código legado ou alguma outra instância?
DougM 28/02
O código crítico de desempenho do @DougM, é uma referência à citação do knuth. Eu também acrescentaria que acho que o erro do coração demonstra que minha visão é a correta, a menos que você não tenha outra escolha, não elimine as verificações de pré-condição em seu código de lançamento
jk.