Na minha opinião, os testes de unidade devem ser colocados em uma montagem separada do código de produção. Aqui estão apenas alguns contras de colocar testes de unidade no mesmo conjunto ou conjuntos que o código de produção:
- Os testes de unidade são enviados com o código de produção. A única coisa fornecida com o código do produto é o código de produção.
- As montagens serão desnecessariamente inchadas por testes de unidade.
- Os testes de unidade podem afetar processos de compilação, como compilação automática ou contínua.
Eu realmente não conheço nenhum profissional. Ter um projeto extra (ou 10) não é um engodo.
Editar: Mais informações sobre compilação e envio
Eu recomendaria ainda que qualquer processo de construção automatizado coloque testes de produção e unidade em locais diferentes. Idealmente, o processo de criação de teste de unidade é executado apenas se o código de produção é construído e copia os arquivos do produto no diretório de testes de unidade. Fazer isso dessa maneira resulta na separação dos bits reais para remessa, etc. Além disso, é bastante trivial executar testes de unidade automatizados neste momento em todos os testes em um diretório específico.
Para resumir, aqui está a idéia geral para uma compilação diária, teste e envio de bits e outros arquivos:
- A construção da produção é executada, colocando os arquivos de produção em um diretório "produção" específico.
- Crie apenas projetos de produção.
- Copie os bits compilados e outros arquivos em um diretório "produção".
- Copie bits e outros arquivos para um diretório candidato a lançamento, também conhecido como diretório de lançamento de Natal, seria "Release20081225".
- Se a construção da produção for bem-sucedida, a construção do teste de unidade será executada.
- Copie o código de produção para o diretório "tests".
- Crie testes de unidade no diretório "tests".
- Execute testes de unidade.
- Envie notificações de compilação e resultados de testes de unidade aos desenvolvedores.
- Quando um candidato a release (como Release20081225) for aceito, envie esses bits.
#if
. Esse símbolo personalizado pode ser alternado usando os parâmetros da linha de comando do compilador nos scripts do software de IC. Consulte msdn.microsoft.com/en-us/library/4y6tbswk.aspx .Projeto separado, mas na mesma solução. (Trabalhei em produtos com soluções separadas para código de teste e produção - é horrível. Você sempre alterna entre os dois.)
As razões para projetos separados são as indicadas por outros. Observe que, se você estiver usando testes orientados a dados, poderá acabar com uma quantidade significativa de inchaço se incluir os testes no conjunto de produção.
Se você precisar acessar os membros internos do código de produção, use InternalsVisibleTo .
fonte
[assembly:InternalsVisibleTo("UnitTestProjectName")]
ao seuAssemblyInfo.cs
arquivo de projeto .Não entendo a objeção frequente à implantação de testes com código de produção. Liderei uma equipe em um pequeno microcap (cresceu de 14 para 130 pessoas). Tínhamos meia dúzia de aplicativos Java e achamos EXTREMAMENTE valioso implantar testes no campo para executá-los em um determinadomáquina que estava exibindo comportamento incomum. Problemas aleatórios ocorrem no campo e ser capaz de lançar alguns milhares de testes de unidade no mistério, com custo zero, foi inestimável e, muitas vezes, diagnosticou problemas em minutos ... incluindo problemas de instalação, problemas de RAM com falhas, problemas específicos de máquina, problemas de rede com falhas, etc, etc. Acho incrivelmente valioso colocar testes em campo. Além disso, problemas aleatórios aparecem em momentos aleatórios e é bom ter os testes de unidade já aguardando para serem executados em um momento. O espaço no disco rígido é barato. Assim como tentamos manter dados e funções juntos (design OO), acho que há algo fundamentalmente valioso em manter código e testes juntos (função + testes que validam as funções).
Gostaria de colocar meus testes no mesmo projeto em C # / .NET / Visual Studio 2008, mas ainda não investiguei isso o suficiente para alcançá-lo.
Um grande benefício de manter o Foo.cs no mesmo projeto que o FooTest.cs é que os desenvolvedores são constantemente lembrados quando uma classe está faltando em um teste de irmão! Isso incentiva as melhores práticas de codificação orientadas a testes ... os buracos são mais aparentes.
fonte
Coloque testes de unidade no mesmo projeto que o código para obter um melhor encapsulamento.
Você pode facilmente testar métodos internos, o que significa que você não tornará públicos métodos que deveriam ter sido internos.
Também é muito bom ter os testes de unidade próximos ao código que você está escrevendo. Ao escrever um método, você pode encontrar facilmente os testes de unidade correspondentes, pois estão no mesmo projeto. Quando você cria um assembly que inclui unitTests, qualquer erro no unitTest fornecerá um erro de compilação, portanto, você deve manter seu unittest atualizado, apenas para compilar. A unificação de um projeto separado pode fazer com que alguns desenvolvedores esqueçam a construção do projeto de unittest e falhem nos testes interrompidos por um tempo.
E você pode remover os testes de unidade do código de produção usando tags de compilação (IF #Debug).
Os testes de integração automática (feitos no iUnit) devem estar em um projeto separado, pois não pertencem a nenhum projeto.
fonte
Release
build e poucos "heisenbugs" podem ocorrer.InternalsVisibleTo
permite testar métodos internos de um projeto de teste separadoDebug
,Approval
eRelease
; e compile a aprovação com todas as otimizações de versão. Além disso, normalmente os testes de unidade não são bons para detectar heisenbugs em primeiro lugar (na minha experiência). Você tende a precisar de testes de regressão de integração específicos para esses - e pode colocá-los lado a lado.Depois de passar algum tempo em projetos TypeScript, onde os testes geralmente são colocados em um arquivo ao lado do código que eles estão testando, passei a preferir essa abordagem do que mantê-los separados:
Então, quando iniciei um novo projeto .NET Core recentemente, queria ver se era possível imitar essa estrutura em um projeto C # sem enviar os testes ou assemblies de teste com a versão final.
A colocação das seguintes linhas no arquivo do projeto parece estar funcionando bem até agora:
O acima assegura que na
Release
configuração todos os arquivos nomeados*.Tests.cs
sejam excluídos da compilação e também que as referências necessárias ao pacote de teste de unidade sejam removidas.Se você ainda deseja poder testar as classes na configuração de liberação, basta criar uma nova configuração derivada de
Release
chamada algo comoReleaseContainingTests
.Atualizar: Depois de usar essa técnica por um tempo, também achei útil personalizar seus ícones no VS Code para fazer com que os testes (e outras coisas) se destacem um pouco mais no painel do explorer:
Para fazer isso, use a extensão Material Icon Theme e adicione algo como o seguinte às suas preferências de código VS JSON:
fonte
Meus testes de unidade sempre vão em um projeto separado. De fato, para cada projeto que tenho na minha solução, há um projeto de teste separado que o acompanha. O código de teste não é um código de aplicativo e não deve ser misturado a ele. Uma vantagem de mantê-los em projetos separados - pelo menos usando o TestDriven.Net - é que posso clicar com o botão direito do mouse em um projeto de teste e executar todos os testes nesse projeto, testando uma biblioteca inteira de código de aplicativo com um clique.
fonte
Se a estrutura do NUnit for usada, há um motivo adicional para colocar os testes no mesmo projeto. Considere o seguinte exemplo do código de produção combinado com testes de unidade:
Os testes de unidade aqui servem como documentação e especificação para o código que está sendo testado. Não sei como obter esse efeito de auto-documentação, com os testes localizados em um projeto separado. O usuário da função precisaria procurar os testes para ver esses casos, o que é improvável.
Atualização : Eu sei que esse uso de
TestCase
atributo não era o que os desenvolvedores do NUnit pretendiam, mas por que não?fonte
Eu flutuo entre o mesmo projeto e projetos diferentes.
Se você está lançando uma biblioteca, liberar o código de teste com o código de produção é um problema, caso contrário, acho que geralmente não é (embora exista uma forte barreira psicológica antes de você tentar).
Ao colocar testes no mesmo projeto, acho mais fácil alternar entre testes e o código que eles testam e mais fácil refatorar / movê-los.
fonte
Coloquei-os em projetos separados. O nome da montagem reflete o dos espaços para nome, como regra geral para nós. Portanto, se houver um projeto chamado Company.Product.Feature.sln, ele terá uma saída (nome do assembly) de Company.Product.Feature.dll. O projeto de teste é Company.Product.Feature.Tests.sln, produzindo Company.Product.Feature.Tests.dll.
É melhor mantê-los em uma única solução e controlar a saída por meio do Configuration Manager. Temos uma configuração nomeada para cada um dos principais ramos (Desenvolvimento, Integração, Produção), em vez de usar o Debug and Release padrão. Depois de definir as configurações, você poderá incluí-las ou excluí-las clicando na caixa de seleção "Compilar" no Gerenciador de Configurações. (Para obter o Configuration Manager, clique com o botão direito do mouse na solução e vá para o Configuration Manager.) Observe que às vezes acho que o CM no Visual Studio está com erros. Algumas vezes, tive que entrar nos arquivos do projeto e / ou solução para limpar os destinos que ele criou.
Além disso, se você estiver usando o Team Build (e tenho certeza de que outras ferramentas de compilação do .NET são iguais), você poderá associar a compilação a uma configuração nomeada. Isso significa que, se você não criar seus testes de unidade para a construção "Produção", por exemplo, o projeto de construção também poderá estar ciente dessa configuração e não construí-los, pois foram marcados como tal.
Além disso, costumávamos fazer o XCopy cair da máquina de compilação. O script omitiria a cópia de qualquer coisa chamada * .Tests.Dll da implantação. Era simples, mas funcionou.
fonte
Eu diria que os mantenha separados.
Além dos outros motivos mencionados, ter código e testes juntos inclina os números de cobertura dos testes. Quando você informa sobre a cobertura do teste de unidade - a cobertura relatada é mais alta porque os testes são cobertos quando você executa testes de unidade. Quando você relata a cobertura do teste de integração, a cobertura relatada é menor porque os testes de integração não executam testes de unidade.
fonte
Estou realmente inspirado pela estrutura de teste de unidade da biblioteca Flood NN de Robert Lopez. Ele usa um projeto diferente para cada classe de unidade testada e possui uma solução contendo todos esses projetos, além de um projeto principal que compila e executa todos os testes.
O interessante também é o layout do projeto. Os arquivos de origem estão em uma pasta, mas a pasta do projeto VS está abaixo. Isso permite criar subpastas diferentes para diferentes compiladores. Todos os projetos do VS são enviados com o código, portanto, é muito fácil para qualquer um executar um ou todos os testes de unidade.
fonte
Sei que essa é uma pergunta muito antiga, mas gostaria de acrescentar minha experiência. Alterei recentemente o hábito de teste de unidade de projetos separados para o mesmo.
Por quê?
Primeiro, sou muito propenso a manter a estrutura da pasta principal do mesmo projeto que o teste. Portanto, se eu tiver um arquivo
Providers > DataProvider > SqlDataProvider.cs
, estou criando a mesma estrutura em meus projetos de teste de unidade, comoProviders > DataProvider > SqlDataProvider.Tests.cs
Mas depois que o projeto está ficando cada vez maior, uma vez que você move arquivos de uma pasta para outra ou de um projeto para outro, fica muito trabalhoso sincronizar os projetos de teste de unidade.
Segundo, nem sempre é muito fácil navegar da classe a ser testada para a classe de teste de unidade. Isso é ainda mais difícil para JavaScript e Python.
Recentemente, comecei a praticar que, a cada arquivo que criei (por exemplo
SqlDataProvider.cs
), estou criando outro arquivo com o sufixo Test, comoSqlDataProvider.Tests.cs
No começo, parece que irá inchar arquivos e referências de bibliotecas, mas a longo prazo, você eliminará a síndrome dos arquivos em movimento à primeira vista e também garantirá que todos os arquivos candidatos a serem testados terão um arquivo emparelhado com
.Tests
sufixo. Isso facilita o acesso ao arquivo de teste (porque fica lado a lado), em vez de procurar um projeto separado.Você pode até escrever regras de negócios para varrer o projeto e identificar a classe que não possui o arquivo .Tests e relatá-las ao proprietário. Além disso, você pode dizer facilmente ao seu executor de teste para direcionar as
.Tests
classes.Especialmente para Js e Python, você não precisará importar suas referências de um caminho diferente; você pode simplesmente usar o mesmo caminho do arquivo de destino que está sendo testado.
Estou usando essa prática há algum tempo e acho que é uma troca muito razoável entre tamanho do projeto x capacidade de manutenção e curva de aprendizado para os novatos no projeto.
fonte
Como outros responderam - coloque testes em projetos separados
Uma coisa que não foi mencionada é o fato de que você não pode realmente executar
nunit3-console.exe
nada além de.dll
arquivos.Se você planeja executar seus testes pelo TeamCity, isso representará um problema.
Digamos que você tenha um projeto de aplicativo de console. Quando você compila, ele retorna um executável
.exe
para abin
pasta.Pelo que
nunit3-console.exe
você não seria capaz de executar nenhum teste definido no aplicativo de console.Em outras palavras, um aplicativo de console retorna um
exe
arquivo e uma biblioteca de classes retornadll
arquivos.Eu só fui mordido por isso hoje e é uma merda :(
fonte
Fui implantando recentemente no docker. Não vejo o valor de ter um projeto separado quando o Dockerfile pode copiar facilmente o diretório / src e sair do diretório / test. Mas eu sou novo no dotnet e pode estar faltando alguma coisa.
fonte
Projetos separados, embora eu discuta comigo mesmo se eles devem compartilhar o mesmo svn. No momento, estou dando a eles repositórios svn separados, um chamado
"MyProject" - para o próprio projeto
e um chamado
"MyProjectTests" - para os testes associados ao MyProject.
Isso é razoavelmente limpo e tem a vantagem de se comprometer com o projeto e se comprometer com os testes, são bastante separados. Isso também significa que você pode entregar o svn do projeto, se necessário, sem precisar liberar seus testes. Isso também significa que você pode ter diretórios branch / trunk / tag para seus testes e para seu projeto.
Mas estou cada vez mais inclinado a ter algo como o seguinte, em um único repositório svn, para cada projeto.
Eu ficaria interessado em saber o que as outras pessoas pensam dessa solução.
fonte