compilação condicional é uma estratégia válida simulação / stub para testes de unidade?

StackOverflow https://stackoverflow.com/questions/97114

Pergunta

Em uma pergunta recente sobre stubbing, muitas respostas sugeriu interfaces de C # ou delegados para a implementação de tocos, mas uma resposta sugeriu o uso de compilação condicional, mantendo a ligação no código de produção estática. Essa resposta foi modded -2 ??no momento da leitura, para pelo menos 2 pessoas realmente pensei que este era um errado resposta. Talvez mau uso de DEBUG foi a razão, ou talvez usar de valor fixo em vez de validação mais extensa. Mas não posso deixar de me perguntar:

É o uso de compilação condicional uma técnica inadequada para a implementação de topos de teste de unidade? As vezes? Sempre?

Graças.

Editar-add: eu gostaria de adicionar um exemplo como um embora experiência:

class Foo {
    public Foo() { .. }
    private DateTime Now { 
      get {
#if UNITTEST_Foo
        return Stub_DateTime.Now;
#else
        return DateTime.Now;
#endif
      }
    }
    // .. rest of Foo members
}

comparando com

interface IDateTimeStrategy { 
    DateTime Now { get; }
}
class ProductionDateTimeStrategy : IDateTimeStrategy {
  public DateTime Now { get { return DateTime.Now; } }
}
class Foo {
    public Foo() : Foo(new ProductionDateTimeStrategy()) {}
    public Foo(IDateTimeStrategy s) { datetimeStrategy = s; .. }
    private IDateTime_Strategy datetimeStrategy;
    private DateTime Now { get { return datetimeStrategy.Now; } }
}

Que permite a dependência de saída em "DateTime.Now" para ser arrancado através de uma interface C #. No entanto, temos agora adicionado uma chamada expedição dinâmico onde estática seria suficiente, o objeto é maior até mesmo na versão de produção, e nós adicionamos um novo caminho fracasso para o construtor de Foo (alocação pode falhar).

Am I se preocupar com nada aqui? Obrigado pelo feedback tão longe!

Foi útil?

Solução

Tente manter o código de produção separada de código de teste. Manter diferentes hierarquias de pastas .. diferentes soluções / projetos.

A menos .. você está no mundo do legado código C ++. Aqui vale tudo .. se blocos condicionais ajudá-lo a obter alguns dos testável código e você vê um benefício .. Por todos os meios fazê-lo. Mas tente não deixá-lo chegar mais confusa do que o estado inicial. Claramente comentar e demarcar blocos condicionais. Prossiga com cuidado. É uma técnica válida para obtenção de código legado em um equipamento de teste.

Outras dicas

Eu acho que diminui a claridade para as pessoas rever o código. Você não deveria ter que lembrar que há uma tag condicional em torno do código específico para entender o contexto.

Sem isso é terrível. Vazamentos de teste em seu código de produção (mesmo que a sua condicionado desligado)

Bad bad.

Código de ensaio deveria ser óbvio e não inter-misturados nos mesmos blocos como o código testado.

Esta é praticamente a mesma razão que você não deve escrever

if (globals.isTest)

Eu pensei em uma outra razão isso foi terrível:

Muitas vezes você zombar / ramal algo, você quer que seus métodos para retornar resultados diferentes dependendo do que você está testando. Isso também se opõe que ou torna complicado como todos Parreira.

Pode ser útil como uma ferramenta para se apoiar como você refatorar a capacidade de teste em uma grande base de código. Eu posso ver como você pode usar essas técnicas para permitir alterações menores e evitar uma refatoração "big bang". No entanto gostaria de se preocupar com inclinando-se demasiado duro na técnica tal e iria tentar garantir que esses truques não viveu muito tempo na base de código caso contrário você corre o risco de tornar o código do aplicativo muito complexo e difícil de seguir.

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