Pergunta

Eu apenas comecei a escrever testes de unidade para um legado módulo de código com grande físico dependências usando a diretiva #include.Eu tenho lidado com eles algumas maneiras que se sentia demasiado entediante (proporcionando vazio cabeçalhos quebra de #incluir listas de dependência, e usando #define para impedir que as classes sejam compilados) e estava procurando algumas melhores estratégias para lidar com estes problemas.

Eu tenho sido frequentemente execução para o problema da duplicação de quase todos os arquivo de cabeçalho com uma versão em branco para separar a classe que eu estou testando em sua totalidade, e, em seguida, escrever substancial de stub/simulação/falso código para objetos que precisam ser substituídos, pois eles são agora indefinido.

Alguém sabe algum melhores práticas?

Foi útil?

Solução

A depressão nas respostas é esmagadora...Mas não tenham medo, nós temos o livro sagrado para exorcizar os demônios do legado de código C++ .Sério apenas comprar o livro, se você está na linha por mais de uma semana do torneio com o legado de código C++.

Voltar para página 127: O caso do horrível incluir dependências. (Agora, eu não sou mesmo dentro de quilômetros de Michael Penas, mas aqui como-curto-como-eu-poderia-gerenciar resposta..)

Problema:Em C++, se uma classA precisa saber sobre ClassB, Classe B declaração é reta levantada / textualmente incluído no ClassA do arquivo de origem.E desde que nós programadores gostam de ter errado extremo, um arquivo pode recursivamente incluir um zilhão de outros transitivamente.Cria-se levar anos..mas ei, pelo menos ele cria..podemos esperar.

Agora dizer 'instanciar ClassA em um equipamento de teste é difícil" é um eufemismo.(Citando MF exemplo do Programador é o nosso cartaz criança problema com deps em abundância.)

#include "TestHarness.h"
#include "Scheduler.h"
TEST(create, Scheduler)     // your fave C++ test framework macro
{
  Scheduler scheduler("fred");
}

Isso vai trazer inclui o dragão com uma enxurrada de erros de compilação.
Sopram#1 Paciência-n-Persistência:Tome em cada incluir um por vez e decidir se realmente precisamos de que a dependência.Vamos supor que SchedulerDisplay é um deles, cujo displayEntry método é chamado Agendador do construtor.
Golpe#2 Falso-que-até-que-fazer-é (Graças RonJ):

#include "TestHarness.h"
#include "Scheduler.h"
void SchedulerDisplay::displayEntry(const string& entryDescription) {}
TEST(create, Scheduler)
{
  Scheduler scheduler("fred");
}

E pop vai a dependência e a todos os seus transitiva inclui.Você também pode reutilizar o Falso métodos encapsulando-lo em um Fakes.h arquivo a ser incluído em seu arquivos de teste.
Golpe#3-A Prática:Ele pode não ser sempre o que é simples..mas você começa a idéia.Após os primeiros duelos, o processo de quebra de deps vai ficar fácil-n-mecânica

Avisos (Eu mencionei há ressalvas?:)

  • Precisamos de um separado para construir casos de teste deste arquivo ;podemos ter apenas 1 definição para o SchedulerDisplay::displayEntry método em um programa.Para criar um programa separado para o programador de testes.
  • Não estamos quebrando todas as dependências no programa, de modo que não são tornando o código mais limpo.
  • Você precisa manter os fakes enquanto precisamos testes.
  • Seu sentido de estética pode ser ofendido por um tempo..apenas morder o lábio e 'urso com a gente para um amanhã melhor'

Use essa técnica para um enorme classe com graves problemas de dependência.Não utiliza frequentemente ou levemente.. Use isso como um ponto de partida para o aprofundamento da refatorações. Ao longo do tempo este programa de testes pode ser tomado atrás do celeiro como extrair mais classes (COM seus próprios testes).

Para mais..por favor, leia o livro.De valor inestimável.Luta no mano!

Outras dicas

Uma vez que você está de testes de código legado eu estou supondo que você não pode refatorar código para ter menos dependências (e.g.usando o pimpl idioma)

Que deixa você com pouco opções que eu tenho medo.Cada cabeçalho que foi incluído para um tipo ou função vai precisar de um objeto de simulação para esse tipo de função ou de tudo para compilar, há pouco que você pode fazer...

Eu não estou respondendo directamente à pergunta, mas estou com medo de que os testes de unidade pode não ser a coisa a fazer se você trabalha com grandes quantidades de código legado.

Depois de liderar uma equipe XP em um campo verde, o projeto de desenvolvimento que eu realmente amei meus testes de Unidade.As coisas aconteceram e alguns anos depois, eu me encontro trabalhando em um grande legado base de código que tem um monte de problemas de qualidade.

Eu tentei encontrar uma maneira de adicionar unidades de testes para a aplicação, mas no final só ficou preso em um catch-22:

  1. Para escrever o significado completo de testes de unidade, o código precisa ser refatorado.
  2. Sem testes de unidade que vai ser muito perigosa para refatorar o código.

Se você se sentir como um herói e beber o cool-auxílio no teste de unidade, em seguida, você pode ainda dar-lhe uma tentativa, mas há um risco real que você possa apenas com mais um teste de código de pouco valor, que agora também precisa ser mantido.

Às vezes é só melhor para trabalhar no código de maneira que é "desenhado" para ser trabalhado.

Eu não sei se isso vai funcionar para o seu projeto, mas você pode tentar atacar o problema a partir do link fase de sua compilação.

Isso seria eliminar completamente o seu #include problema.Tudo que você precisa fazer é re-implementar as interfaces em arquivos incluídos para fazer o que quiser e, em seguida, apenas um link para o objeto de simulação de arquivos que foram criados para implementar as interfaces no arquivo de inclusão.

A grande desvantagem deste método é mais complected sistema de compilação.

Se você continuar a escrever stubs/simulação/códigos falsos você corre o risco de fazer o teste de unidade em uma classe que tenha um comportamento diferente, em seguida, quando compilado no projeto principal.

Mas se esses inclui existem e não têm adicionado comportamento, então é Ok.

Eu ia tentar não alterar nada sobre o inclui ao fazer o teste de unidade que você está certo (como distante você pode ser em código legado :) ) que você teste o código real.

Você está definitivamente entre uma rocha e um lugar duro com código legado com grandes dependências.Você tem um longo e duro caminho pela frente para resolver tudo isso.

A partir do que você diz, parece que você está tentando manter o código-fonte intacta para cada módulo, por sua vez, colocando-a em um equipamento de teste com dependências externas zombaram de fora.Minha sugestão aqui seria a de tomar o mesmo corajoso passo de tentar algumas refatorações para eliminar (ou inverter) as dependências, que é provavelmente o passo que você está tentando evitar.

Sugiro isso porque eu estou supondo que as dependências vão matar você como você escrever testes.Você certamente vai ser melhor em longo prazo, se você pode eliminar as dependências.

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