Olá pessoal, vamos de Visual Studio hoje.
Imagine um cenário bem comum: Estamos desenvolvendo um projeto que manipula arquivos e, para ajudar o desenvolvimento, você cria uma classe utilitária que lê do arquivo de configuração qual é o repositório local (diretório) onde os arquivos são armazenados. Essa classe auxiliar será utilizada por toda aplicação, então não existirá somente para testes. Exemplo de código abaixo:
public class Configuração
{
private static string repositórioArquivos;
static Configuração() {
repositórioArquivos = ConfigurationManager.AppSettings["RepositórioArquivos"];
}
public static string RepositórioArquivos {
get { return repositórioArquivos; }
}
}
public void RenomearArquivo(string nomeArquivo, string novoNomeArquivo) {
string repositório = Configuração.RepositórioArquivos;
File.Move(Path.Combine(repositório, nomeArquivo), Path.Combine(repositório,
novoNomeArquivo));
}
Antes ou depois de codificar a classe, você desenvolve alguns testes para testar seu componente, então para tudo funcionar corretamente você adiciona ao seu projeto de testes um arquivo App.Config e colocar uma entrada no AppSettings, que será lida pelo auxiliar de configuração:
public void TesteCenárioUsoBásico() {
// Pré-condições
Assert.IsTrue(File.Exists(Path.Combine(
TestesComArquivos.Configuração.RepositórioArquivos, "arquivoqualquer.txt")));
TestesComArquivos.ClasseNegocio negócio = new TestesComArquivos.ClasseNegocio();
negócio.RenomearArquivo("arquivoqualquer.txt", "novoarquivotexto.txt");
// Pós-condições
Assert.IsTrue(File.Exists(Path.Combine(
TestesComArquivos.Configuração.RepositórioArquivos, "novoarquivotexto.txt")));
}
Execute o projeto (em anexo a este artigo) e tudo funcionará perfeitamente. Quer dizer, mais ou menos, pois aqui temos alguns problemas:
1 - Depois que você executar esse teste, o arquivo estará renomado e a próxima execução vai falhar. Você corrige isso escrevendo direito as pré-condições e setup do seu teste. Por simplicidade eu deixarei como está, ok?
Tudo isso funciona corretamente se você está desenvolvendo sozinho, mas e se houver uma equipe junto com você?
2 - Em primeiro lugar, os arquivos não serão levados juntos com o projeto, então se alguém adiciona outro arquivo para teste, o que você faz? Isso garoto, adicione os arquivos ao projeto de teste, para todos os desenvolvedores terem acesso ao distinto quando pegarem uma nova versão do projeto.
3 - (Um problema de verdade) Cada desenvolvedor pode definir um diretório local diferente para seu workspace de trabalho, então se um desenvolvedor colocar os arquivos da solução em outro diretório e mudar o App.Config, quando você pegar a última versão do projeto no TFS, bye bye testes!
Uma maneira de "resolver" isso é ficar mudando o App.Config para cada desenvolvedor ou então padronizar o diretório local para o seu projeto, mas é um gato MUITO feio. Concorda? E se houverem builds diários, você vai fazer o quê? Como resolvemos isso?
- Adicione ao seu projeto o diretório "Arquivos" e coloque lá dentro o famoso "arquivoqualquer.txt". Lembre de marcar a opção do arquivo "Copy to output directory" com "Copy if newer".
- Como a cada nova execução dos testes são gerados novos diretórios com um timestamp diferente (ex.: "C:\Projects\VisualStudio\TestesComArquivos\TestResults\luciano.moreira_DSKSRN01 2009-10-26 14_26_18"), precisamos referenciar os arquivos dentro do diretório "Out", onde estão as DLLs do projeto.
- Como nossa propriedade em Configuração.RepositórioArquivos é somente leitura e não queremos interferir com a interface da classe, adicionarei um método internal chamado DefineRepositórioArquivos.
internal static void DefineRepositórioArquivos(string repositório) {
repositórioArquivos = repositório;
} - Para que esse método seja visível no nosso projeto de testes, utilizamos um pequeno recurso do .NET, definindo que os métodos internal do assembly de negócio são visíveis somente para o projeto de testes. Recurso que somente utilizo nesse tipo de cenário.
[assembly: InternalsVisibleTo("TestesComArquivos_TesteSuite")]
- A partir desse momento eu faço uma pequena alteração no setup do meu teste, para que ele defina qual o repositório de arquivos de acordo com o diretório de deployment do teste. Para isso eu utilizo a classe auxiliar TestContext, que possui a propriedade DeploymentDirectory. Se você não quiser usar essa classe auxiliar, pode partir para a ignorância com o AppDomain.CurrentDomain.BaseDirectory.
TestesComArquivos.Configuração.DefineRepositórioArquivos(TestContext.DeploymentDirectory);
Se você executar o seu teste nesse momento irá receber um erro! Analisando com cuidado verificará que o problema está no primeiro Assert, que pergunta pela existência do arquivo, então olhando o diretório criado pelos testes notará que o arquivo não foi colocado no Out. Huummm, mas no passo 1 você já pediu para o arquivo ser copiado para o diretório de saída, não é suficiente?
O pior é que não! Quando você compila o projeto de teste o arquivo é colocado no "\Bin\Debug" corretamente, mas não é levado para o "\TestResult\....\Out" que é criado para o teste. Para isso é necessário editar as configurações dos testes em "Local.testsettings" (dentro de Solution Items) e no Deployment adicionar o diretório "Arquivos", conforme figura abaixo.
Pronto!
Basta executar o seu teste que tudo vai funcionar e quantas vezes forem necessárias, pois cada novo teste copia o arquivo original para um novo diretório, evitando o primeiro problema que eu citei. Agora todos os seus desenvolvedores podem trabalhar tranquilamente, adicionar novos arquivos ao diretório já criado e codificar novos testes, basta lembrar de definir o diretório correto no início dos testes.
Bom, espero que tenham gostado. O projeto que criei está disponível juntamente com o PDF do artigo. Baixe aqui.
Luciano Caixeta Moreira - {Luti}
Chief Innovation Officer Sr. Nimbus Serviços em Tecnologia Ltda luciano.moreira@srnimbus.com.br
www.twitter.com/luticm
Nenhum comentário:
Postar um comentário