Essa é uma continuação do post anterior:

Testando o banco de dados: com Infra Microsoft

Nesse vou apresentar a mesma solução, mas usando outras ferramentas, quase todas open source. Por isso eu quero dizer tudo mesmo, só vou manter o Visual Studio de padrão.

Vamos ao cardápio:

Todo o projeto está no BitBucket para download. Você pode baixá-lo aqui e vê-lo online aqui.

Vamos começar pelos testes. Vou continuar no estilo AAA para testar:

using ClassLibrary1;
using NHibernate;
using MbUnit.Framework;

namespace TestProject1.Testes
{
    [TestFixture]
    public class TesteConsulta : TesteBase
    {
        private const int IdParaConsultar = 1;
        private ISession _session;
        private Produto _produtoEncontrado;

        [SetUp]
        public void Initialize()
        {
            Arrange();

            Act();
        }

        private void Arrange()
        {
            _session = Contexto.SessionFactory.OpenSession();
        }

        private void Act()
        {
            _produtoEncontrado = _session.Get<Produto>(IdParaConsultar);
        }

        [Test]
        public void ExisteNoBD()
        {
            Assert.IsNotNull(_produtoEncontrado);
        }
        [Test]
        public void TemNomeCorreto()
        {
            Assert.AreEqual("meu nome", _produtoEncontrado.Nome);
        }
    }
}

O primeiro a notar é que estamos usando MbUnit, como framework de testes. Ele é o responsável pelos atributos TestFixture na classe e Setup e Test nos métodos. O Gallio é parte do MbUnit (ou vice versa) e roda os testes. Ao rodar este é o resultado:

image

Esse resultado é obtido rodando com o TestDriven.Net. Com ele, posso clicar em qualquer lugar e rodar qualquer teste. Fica muito fácil, e como ele é especializado em rodar testes unitários, ele roda um pouco mais rápido que o runner do MSTest. Veja como rodar com TDD.Net na classe:

image

Mais fácil impossível, né? E dá para rodar também via Powershell:

Rodando:

image

Terminou de rodar, resultados:

image

O resultado é apresentado também com um relatório HTML. Publiquei o relatório de uma rodada completa de testes aqui no blog se alguém quiser dar uma olhada no resultado. O legal é que dá pra ver até os sqls gerados pelo NHibernate.

Se rodarmos todos os testes, o resultado é esse:

image

E para isso, basta clicar no projeto e mandar rodar:

image

Ok, chega de telinhas, vamos voltar para o teste.

Estamos usando NHibernate, e a sessão do NH (análoga ao contexto do Entity Framework), é aberta via SessionFactory, que está armazenada em uma classe chamada contexto, em uma propriedade estática:

public class Contexto
{
    public static ISessionFactory SessionFactory { get; set; }
}

Esse código seria usado também pela aplicação real, além dos testes. Estamos só reaproveitando. Logo mais vou mostrar como essa variável é configurada.

O método de ação bate no NH, que bate no banco, e obtem o produto com Id igual a 1. Esse é o método Act.

Os testes são verificações simples da existência do produto, e de sua propriedade Nome.

Tenho testes para exclusão e inclusão também. Esse é o de exclusão:

[TestFixture]
public class TesteExclusao : TesteBase
{
    private const int IdParaExcluir = 1;
    private ISession _session;

    [SetUp]
    public void Initialize()
    {
        Arrange();

        Act();
    }

    private void Arrange()
    {
        _session = Contexto.SessionFactory.OpenSession();
    }

    private void Act()
    {
        var produtoParaExcluir = _session.Get<Produto>(IdParaExcluir);
        using (var tran = _session.BeginTransaction())
        {
            _session.Delete(produtoParaExcluir);
            tran.Commit();
        }
    }

    [Test]
    public void NaoEstaNoBD()
    {
        _session.Clear();
        var produtoExcluido = _session.Get<Produto>(IdParaExcluir);
        Assert.IsNull(produtoExcluido);
    }
}

Neste eu excluo o Id igual a 1, e depois testo se o produto foi removido do banco, limpando a sessão para evitar cache, e fazendo novamente a consulta.

Posso rodar este teste quantas vezes quiser. Como ele continua funcionando?

Vocês já devem ter notado que os testes herdam de TesteBase. Vamos ver esta classe:

public abstract class TesteBase 
{
    [SetUp]
    public virtual void TestInitialize() 
    {
        OperacoesDeTestes.CarregarBancoDeDados(ConfiguracaoDeTestes.Esquema, ConfiguracaoDeTestes.DadosDeTeste);
    }
}

Notaram que ela faz uma carga do banco de dados, sempre antes de um teste rodar? É assim que garanto que o teste de exclusão nunca vai falhar por não encontrar produto para excluir, ou que o teste de inclusão vai falhar ao consultar e receber nulo.

Esta classe colabora com a classe OperacoesDeTestes. Esta classe, na prática, é só um wrapper em volta do NDbUnit. O NDbUnit é responsável por subir os dados no banco de dados, e ele também pode baixá-los. Ele faz isso com xml e xsd. Aqui vocês vêem os métodos desta classe:

public static class OperacoesDeTestes
{
    public static void CarregarBancoDeDados(
        string esquema,
        string dados)
    {
        var baseDeDados = ObterBaseDeDados();
        baseDeDados.ReadXmlSchema(esquema);
        baseDeDados.ReadXml(dados);
        baseDeDados.PerformDbOperation(DbOperationFlag.CleanInsertIdentity);
    }

    private static INDbUnitTest ObterBaseDeDados()
    {
        var baseDeDados = new SqlDbUnitTest(ConfiguracaoDeTestes.StringDeConexao);
        return baseDeDados;
    }

}

Notem que o método CarregarBancoDeDados lê o schema e o xml, e salva no banco, limpando os campos identity, se existirem, sempre usando o NDbUnit.

E de onde vem os dados? Há uma classe chamada ConfiguracaoDeTestes. Vejam ela:

public class ConfiguracaoDeTestes
{
    public static string DiretorioDeDados;
    public static string DadosDeBackup;
    public static string DadosDeTeste;
    public static string Esquema;
    public static string StringDeConexao;

    public static void InicializarVariaveisDeTeste(
        string basedir,
        string stringDeConexao)
    {
        StringDeConexao = stringDeConexao;
        DiretorioDeDados = Path.Combine(basedir, @"Dados\");
        DadosDeBackup = Path.Combine(DiretorioDeDados, "DadosBackup.xml");
        DadosDeTeste = Path.Combine(DiretorioDeDados, "Dados.xml");
        Esquema = Path.Combine(DiretorioDeDados, "Schema.xsd");
    }
}

Na prática ela somente segura valores de configuração, para que possam ser acessados facilmente de qualquer lugar. Entre os dados estão os diretórios onde guardamos os arquivos xml e xsd. Esta classe recebe seus valores de outra, chamada AssemblyInitialize.

Todo bom framework de testes permite fazer um setup inicial, que roda antes de todos os testes. O MbUnit não é diferente. Para permitir isso, basta usar o atributo AssemblyFixture sobre uma classe, e usar os métodos Setup e TearDown para preparar o ambiente de testes e desmontá-lo, respectivamente.

No meu caso, na inicialização do teste, preciso inicializar as variáveis de teste, que ficam na classe de configuração vista anteriormente, preciso configurar o NHibernate, e atualizar o esquema do banco de dados. Ufa, vamos ver como fica:

[AssemblyFixture]
public class AssemblyInitializer
{
    [SetUp]
    public static void AssemblyInitialize()
    {
        var baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        ConfiguracaoDeTestes.InicializarVariaveisDeTeste(baseDir, StringDeConexao);
        ConfigurarNHibernateESubirEsquemaDoBancoDeDadosDeDominio();
    }

Aqui estamos declarando a classe e o método de inicialização. Estou obtendo o caminho do assembly em execução. É lá que fica meu xml e meu xsd. E passo isso, mais a string de conexão, para configurar o ambiente. Em seguida, configura o NH e subo o esquema do banco de dados.

Não vou entrar em detalhes de como o NH sobe o banco de dados, você pode ver a classe de configuração lá no BitBucket. Na prática a operação se chama schema update, onde ele compara o banco que está em produção com o que ele tem, e atualiza tudo.

Quero mostrar aqui a parte do NbUnit. Eu configuro ele com um xsd, criado a partir de um dataset tipado. Sim! Um dataset tipado. Eles ainda existem! Esse é o único lugar onde eu tenho usado datasets tipados nos últimos anos, e faz total sentido. Vejam ele, chamado de schema.xsd, aqui:

image

Notem três coisas. Primeiro: arranquei os table adapters, não precisamos dele, só queremos o xsd. Como queremos só o xsd, apaguei a custom tool, que fica na janela de propriedades. Sem custom tool, não há geração do arquivo que gera o dataset, isso elimina a criação do arquivo Schema.cs.

Isso me dá o schema que preciso para preparar o banco de dados. Basta então digitar o xml. O xml é muito simples:

<?xml version="1.0" encoding="utf-8" ?>
<Schema xmlns="http://tempuri.org/Schema.xsd">
  <Produto>
    <Id>1</Id>
    <Nome>meu nome</Nome>
  </Produto>
  <ProdutoId>
    <NextHi>1</NextHi>
  </ProdutoId>
</Schema>

Usando o namespace correto, ele funciona perfeitamente e o Visual Studio ainda valida o xml enquanto você escreve.

Basta então, apenas configurar estes dois arquivos para serem copiados para o diretório de testes.

image

Ao rodar o método OperacoesDeTestes.CarregarBancoDeDados, e passar este xml e xsd como parâmetros, tudo funciona. Os dados vão parar no banco de dados conforme o esperado.

E com isso fecho o ciclo completo: atualizo o schema do banco, subo os dados, e testo. A partir da criação desta pequena infra, é só escrever os testes livremente, sempre herdando de TesteBase.

O que acharam? Qual preferem, com infra Microsoft, ou infra (semi)open? Porque?


Postado na(s) categoria(s) Testes pelo Giovanni Bassi em 27 de agosto de 2010 às 02:48 | Tags: ,

Não, AAA não é só uma pilha, é também uma forma de testar. O que eu vou mostrar aqui talvez você já conheça, talvez você já faça, mas talvez nunca tenha parado pra pensar no assunto.

  1. Todo teste passa por uma preparação, seja de ambiente, variáveis, banco de dados, etc. Essa preparação pode ser chamada em inglês de Arrange. Nosso primeiro A.
  2. Em seguida, todo teste passa por um momento onde estimulamos o sistema sendo testado (System Under Test em inglês, ou SUT). Isso é o Act, nosso segundo A.
  3. E logo em seguida, verificarmos se os resultados obtidos batem com os resultados esperados. Isso é o Assert, o terceiro A.

Essa não é a única forma de definir o ciclo de testes, há outras. Mas essa é uma das mais fáçeis de entender. Vamos pegar um teste comum, e vamos transformá-lo num testes triple-A. Vejam o teste abaixo, onde testo uma calculadora:

[TestClass]
public class TestaCalc
{
    [TestMethod]
    public void TesteSoma()
    {
        var calculadora = new Calculadora();
        var resultado = calculadora.Somar(2, 3);
        Assert.AreEqual(5, resultado);
    }
}

public class Calculadora
{
    public int Somar(int a, int b)
    {
        return a + b;
    }
}

Posso evidenciar os três As assim:

[TestClass]
public class TestaCalc
{
    [TestMethod]
    public void TesteSoma()
    {
        //arrange:
        var calculadora = new Calculadora();
        //act:
        var resultado = calculadora.Somar(2, 3);
        //assert:
        Assert.AreEqual(5, resultado);
    }
}

Mas isso não muda nada o que eu já estava fazendo.

Já ouviram falar que cada teste só pode testar uma coisa? Já tentou fazer isso? Já viu como é difícil se não pensarmos de forma estruturada? E o problema é mesmo a estrutura. Vou propor uma mudança estrutural.

Inicio separando a preparação (Arrange) e o estímulo (Act), das verificações (Asserts). Isso é fácil de fazer, a primeira ação é criar a ideia de contexto, que no teste anterior da calculadora não existia, e na prática, ficava encapsulado no método. O contexto vai ser aplicado à classe, e não mais ao método. O contexto do teste é a calculadora. O contexto é preparado e estimulado na inicialização do teste.

Toda classe fica com mais ou menos essa estrutura:

[TestClass]
public class Teste
{
    [TestInitialize]
    public void Inicializar()
    {
        Arrange();

        Act();
    }

    private void Arrange()
    {
        //prepara
    }

    private void Act()
    {
        //executa
    }

    [TestMethod]
    public void VerificaAlgo()
    {
        //faz as verificaoes
    }
    
    [TestMethod]
    public void VerificaAlgoAMais()
    {
        //faz outras verificaoes
    }
}

Para traduzir o teste de calculadora fica fácil. Coloco a criação da calculadora no arrange, a soma no Act, e as verificações no teste em si.

[TestClass]
public class DadaUmaCalculadoraQueSoma2Mais3
{
    private Calculadora _calculadora;
    private int _resultado;

    [TestInitialize]
    public void Inicializar()
    {
        Arrange();

        Act();
    }
    private void Arrange()
    {
        _calculadora = new Calculadora();
    }
    private void Act()
    {
        _resultado = _calculadora.Somar(2, 3);
    }
    [TestMethod]
    public void Totaliza5()
    {
        Assert.AreEqual(5, _resultado);
    }
}

Com isso, apenas separamos o teste em três métodos diferentes, e pode ser que não esteja valendo a pena.

A ideia começa a ficar mais interessantes quando o teste fica mais complexo. O teste passa a ser auto-explicativo, e as falhas passam a ficar mais evidentes. O exemplo a seguir deixa isso claro:

[TestClass]
public class TestaServicoEmissaoNFEmitindoNF
{
    private ServicoEmissaoNF _servico;
    private Pedido _pedido;
    private NotaFiscal _nf;
    private EnviadorDeMensagensFake _enviador;

    [TestInitialize]
    public void Inicializar()
    {
        Arrange();

        Act();
    }

    private void Arrange()
    {
        _pedido = new Pedido(500);
        _enviador = new EnviadorDeMensagensFake();
        _servico = new ServicoEmissaoNF(_enviador);
    }

    private void Act()
    {
        _nf = _servico.Emitir(_pedido);
    }

    [TestMethod]
    public void NFNaoÉNula()
    {
        Assert.IsNotNull(_nf);
    }
    
    [TestMethod]
    public void ValorDaNFÉIgualAoValorDoPedido()
    {
        Assert.AreEqual(_pedido.Valor, _nf.Valor);
    }

    [TestMethod]
    public void MensagemEhEnviada()
    {
        Assert.IsFalse(string.IsNullOrWhiteSpace(_enviador.MensagemEnviada));
    }
}

Nesse cenário, crio uma nota fiscal a partir de um pedido, e verifico 3 coisas: a NF é criada (não é nula), o valor da NF é igual ao valor do pedido, e uma mensagem é enviada durante o processo. Cada um é um único teste.

Poderia fazer isso sem o AAA explícito? Poderia. Ficaria assim:

[TestClass]
public class TestaServicoEmissaoNF
{
    [TestMethod]
    public void EmissaoDaNF()
    {
        //arrange
        var pedido = new Pedido(500);
        var enviador = new EnviadorDeMensagensFake();
        var servico = new ServicoEmissaoNF(enviador);
        //act
        var nf = servico.Emitir(pedido);
        //assert
        Assert.IsNotNull(nf);
        Assert.AreEqual(pedido.Valor, nf.Valor);
        Assert.IsFalse(string.IsNullOrWhiteSpace(enviador.MensagemEnviada));
    }
}

Porque eu não faria isso num cenário como esse?

  1. O teste testa 3 coisas diferentes;
  2. Se o primeiro assert falhar, eu não sei se os outros passaram;
  3. O método testa coisa demais, isso fica evidente pelo nome do método de teste

É uma troca de expressividade e manutenibilidade por velocidade na escrita do código. Como a diferença de velocidade é mínima, e a perda de expressividade é alta, eu decido por não fazer.

Isso fica ainda mais fácil se você criar uma classe abstrata para testes. Algo assim:

public abstract class TesteBase
{
    [TestInitialize]
    public void Inicializar()
    {
        Arrange();

        Act();
    }

    protected virtual void Arrange()
    {
    }

    protected abstract void Act();
}

Assim, o Arrange é opcional, o Act é obrigatório, e os testes você implementa como quiser.

Depois eu conto como melhorar isso ainda mais. Em breve. Estou devendo alguns posts…


Postado na(s) categoria(s) Testes pelo Giovanni Bassi em 18 de agosto de 2010 às 19:11 | Tags:

(Update: Veja também o artigo irmão deste: Testando o banco de dados: com infra não Microsoft)

Eu testo minhas aplicações, e algo que não pode ficar de fora é o teste do banco de dados. Vocês sabem que eu não gosto de colocar regras de negócio no banco de dados (e isso é assunto para outra discussão), então para mim, testar o banco de dados é testar a interação da aplicação com o banco de dados. E eu uso ORMs, ou seja, na verdade, o que eu preciso testar é a se o meu mapeamento está funcionando e se o schema do banco está correto, de acordo com o que a aplicação espera.

Neste post eu vou mostrar como fazer isso com infra Microsoft, ou seja, com Data Dude (VS Database) e Entity Framework. No próximo vou mostrar com alguns componentes open source. O próximo vem semana que vem.

Você só precisa de um Visual Studio 2010 Premium, porque na edição professional não vem o Data Dude, que é o antigo VS Database edition, que não existe mais. Ele tem um projeto de banco de dados, e vou usá-lo.

Mas antes de mais nada…

Como testar algo que interage com o banco de dados? É óbvio que se interage com o BD, não pode ser um teste unitário, tem que ser um teste integrado, nesse caso, integrado com o banco. O que testar?

Os testes vão manipular o banco, vão incluir, alterar, excluir, e consultar, ou seja, vão fazer operações CRUD. Quando um teste altera os dados do banco pode ser que ele altere o resultado de outro teste. Por exemplo, em um teste eu incluo um item em uma nota fiscal e salvo, antes ela tinha 10, agora tem 11. Em outro teste eu consulto a mesma nota, e verifico se ela tem 10 itens, o teste falha, porque o teste que inseriu o teste rodou antes. Eu até poderia determinar a ordem dos testes, mas isso deixaria meu plano de testes confuso e ruim: jamais poderia rodar um único teste sem antes rodar os outros. Testes devem rodar sempre independentes uns dos outros. Como resolver? A cada teste o banco deve ter seus dados reiniciados. Como subir estes dados? Já vi pessoas usarem transações, e dar rollback no final, mas isso é no mínimo incompleto: quem sobe os dados iniciais? É feito na mão? Além disso, o esquema tem que estar atualizado. Não dá pra testar se falta uma tabela, uma coluna, ou se há alguma diferença. Nossa infra de testes deve resolver esse problema.

Primeiro vamos resolver o problema do esquema. O Data Dude tem um projeto de banco de dados. Vejam lá, File > New > Project > Database > SQL Server > SQL Server 2008 Database Project (clique nas imagens para ampliar):

image

Esse projeto cria todo o esquema que você vai precisar e também os dados. Não vou explicar aqui o que é o Data Dude, mas confie em mim, funciona e é muito legal. Para mais informações, baixe o training kit, baixe a VM, e/ou veja online a documentação.

Criei também um projeto class library e fiz um mapeamento simples no EF, vejam só:

image

Esse mapeamento já gerou a classe de produto e também o contexto que eu quero testar.

Gerei o SQL, importei ele pro projeto de database:

image

E tenho o schema lá:

image

Eu quero ter uma carga de dados, então criei um plano de geração de dados, ou data generation plan:

image

Ele gera dados para minhas tabelas, vou precisar disso mais pra frente.

Criei um projeto de testes, e pra ganhar tempo, pedi pra criar um teste de banco de dados, que vai me ajudar na criação da infra de testes com banco:

image

Ele me dá a opção de gerar meu banco (fecha azul), e incluir o meu plano de geração de dados (flecha vermelha).

image

Ao fazer isso, vários artefatos interessantes apareceram no meu projeto. Vamos vê-los. Primeiro meu web.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="DatabaseUnitTesting" type="Microsoft.Data.Schema.UnitTesting.Configuration.DatabaseUnitTestingSection, Microsoft.Data.Schema.UnitTesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </configSections>
    <DatabaseUnitTesting>
        <DatabaseDeployment DatabaseProjectFileName="..\..\..\Database1\Database1.dbproj"
            Configuration="Debug" />
        <DataGeneration DataGenerationFileName="..\..\..\Database1\Data Generation Plans\DataGenerationPlan1.dgen"
            ClearDatabase="true" />
        <ExecutionContext Provider="System.Data.SqlClient" ConnectionString="Data Source=.\sqlexpress;Initial Catalog=TesteIntegradoBanco;Integrated Security=True;Pooling=False"
            CommandTimeout="30" />
        <PrivilegedContext Provider="System.Data.SqlClient" ConnectionString="Data Source=.\sqlexpress;Initial Catalog=TesteIntegradoBanco;Integrated Security=True;Pooling=False"
            CommandTimeout="30" />
    </DatabaseUnitTesting>
</configuration>

O Web.config está com toda a configuração para gerar o banco e fazer o deploy dos dados, inclusive o ponteiro para o data generation plan.

Foi criada também esta classe:

[TestClass]
public class DatabaseSetup
{
    [AssemblyInitialize]
    public static void InitializeAssembly(TestContext ctx)
    {
        DatabaseTestClass.TestService.DeployDatabaseProject();
        DatabaseTestClass.TestService.GenerateData();
    }

}

Notem o atributo AssemblyInitialize. Ele indica que quando antes deste assembly de teste rodar, este método será executado. Ele fará duas coisas: subirá o schema do banco de dados (método DeployDatabaseProject) e gerará os dados (método GenerateData). Esse segunda chamada de método não vai ficar aí, mas por enquanto tudo bem.

Agora eu posso excluir o teste de banco de dados que foi criado, ele servia pra criar os artefatos.

Agora só falta criar o teste que testa a interação com o banco em si. Vamos adicionar a classe de testes, usando o novo basic test, que vem sem aquele monte de linhas que eu sempre apago:

image

Ela fica assim:

[TestClass]
public class TesteInclusao
{
    private Produto _produtoParaIncluir;
    private Model1Container _container;

    [TestInitialize]
    public void Initialize()
    {
        Arrange();

        Act();
    }

    private void Arrange()
    {
        _container = new Model1Container();
        _produtoParaIncluir = new Produto
                       {
                           Nome = "um"
                       };
    }
    
    private void Act()
    {
        _container.AddToProdutoes(_produtoParaIncluir);
        _container.SaveChanges();
    }
   
    [TestMethod]
    public void NaoEhIgualAZero()
    {
        Assert.AreNotEqual(0, _produtoParaIncluir.Id);
    }

    [TestMethod]
    public void EstaNoBD()
    {
        var outroContainer = new Model1Container();
        var produtoIncluido = outroContainer.Produtoes.Single(p => p.Id == _produtoParaIncluir.Id);
        Assert.AreEqual("um", produtoIncluido.Nome);
    }
}

Notem que estou testando diretamente o container do Entity Framework.

O teste deve passar. Não esqueça de puxar as strings de conexão do projeto de class library para o projeto de testes, senão o container não vai ser criado. O banco subiu, o dado foi inserido. Você pode realizar uma consulta manual e confirmar, se você não acreditar no seu teste.

E um teste para excluir? Será que fuciona? Vamos olhar os dados gerados no plano de geração de dados:

image

Posso pedir para consultar por id, ou por nome, e então excluir. Vou pedir por id, que é gerado automaticamente por identity no SQL Server. Vejam o teste:

 

[TestClass]
public class TesteExclusao
{
    private const int IdParaExcluir = 1;
    private Model1Container _container;

    [TestInitialize]
    public void Initialize()
    {
        Arrange();

        Act();
    }

    private void Arrange()
    {
        _container = new Model1Container();
    }
    
    private void Act()
    {
        var produtoParaExcluir = _container.Produtoes.Single(p => p.Id == IdParaExcluir);
        _container.DeleteObject(produtoParaExcluir);
        _container.SaveChanges();
    }
   
    [TestMethod]
    public void NaoEstaNoBD()
    {
        var outroContainer = new Model1Container();
        var produtoExcluido = outroContainer.Produtoes.SingleOrDefault(p => p.Id == IdParaExcluir);
        Assert.IsNull(produtoExcluido);
    }
}

E funciona!


Se em outro teste eu quiser consultar o id 1, eu poderia ter problemas, já que o teste de exclusão poderia interferir. Para resolver isso eu puxo para o teste de consulta o setup dos dados no banco, veja a chamada de GenerateData, destacada.

 

[TestClass]
public class TesteConsulta
{
    private const int IdParaConsultar = 1;
    private Model1Container _container;
    private Produto _produtoEncontrado;

    [TestInitialize]
    public void Initialize()
    {
        Arrange();

        Act();
    }

    private void Arrange()
    {
        _container = new Model1Container();
        DatabaseTestClass.TestService.GenerateData();
    }
    
    private void Act()
    {
        _produtoEncontrado = _container.Produtoes.SingleOrDefault(p => p.Id == IdParaConsultar);
    }
   
    [TestMethod]
    public void ExisteNoBD()
    {
        Assert.IsNotNull(_produtoEncontrado);
    }
    [TestMethod]
    public void TemNomeCorreto()
    {
        Assert.AreEqual("aquele dado gigante gerado", _produtoEncontrado.Nome);
    }
}

Isso garante a consistência dos dados entre os testes.

 

Com isso posso criar testes à vontade, o banco sempre vai ter o último esquema e dados atualizado. Não preciso me preocupar com os dados, eles sempre vão estar lá. Isso é o básico dos testes integrado com banco de dados. O Visual Studio permite toda essa integração de maneira simples. Esse tipo de cenário fica especialmente importante quando não usamos ORMs, já que todo o acesso a dados é manual, e nesse caso testamos nossos DAOs, e também quando usamos POCO, onde o mapeamento é mais manual do que o que usei aqui.

No próximo vou mostrar como resolver isso sem o Data Dude, já que ele está limitado ao SQL Server e aos poucos providers extras que foram feitos até agora. E sem Entity Framework também.


Postado na(s) categoria(s) Team System , Testes pelo Giovanni Bassi em 19 de julho de 2010 às 19:02 | Tags: ,

Subi os slides da palestra de testes unitários/integrados que dei no .Net Architects no último sábado. Para quem se interessar, segue abaixo:

Além disso há o áudio online, já que gravamos toda a reunião com o Live Meeting. Em breve teremos também o vídeo da palestra em si, onde você poderá ver o vídeo da palestra e também os slides, lado a lado. O vídeo que temos neste momento está em formato de webcast. Você pega ele aqui:

https://www323.livemeeting.com/cc/usergroups/view?id=9FG48Q

Os links do slide, para facilitar, estão aqui:

Blogs:
JW on Tests: http://blogs.msdn.com/james_whittaker/
Giggio on Tests: http://unplugged.giggio.net?tag=/teste

Ferramentas:
Mocks:
Rhino Mocks: http://ayende.com/projects/rhino-mocks.aspx
Moq: http://code.google.com/p/moq
TypeMock: http://www.typemock.com
Setup:
NDbUnit: http://code.google.com/p/ndbunit
Rodadores de testes:
MSTest/VSTS: http://gofrom.us/14E5
nUnit: http://www.nunit.org
MbUnit/Gallio: http://www.gallio.org
xUnit: http://www.codeplex.com/xunit
Resharper: http://www.jetbrains.com/resharper

Giovanni Bassi:
Blog: http://unplugged.giggio.net
Consultoria: http://www.giovannibassi.com


Postado na(s) categoria(s) Testes , Arquitetura pelo giovanni bassi em 14 de maio de 2009 às 01:42 | Tags: ,

Acaba de ser lançado um novo Release Candidate da versão 3.5 do Rhino Mocks, com várias novas funcionalidades e uma proximidade maior do C# 3.0.

Eu gosto bastante deste framework de mocking e recomendo. Em todo trabalho que supervisiono, toda arquitetura que crio, testes unitários são uma recomendação obrigatórias e um framework de mocking ajuda muito, ainda mais se for bem feito como este.

Se você não conhece o assunto eu ajudo: mocks são uma maneira de “ajudar” nos de testes unitários automáticos. Você pode ver um pouco mais na Wikipedia e bem mais no meu artigo da próxima edição da .Net Magazine (julho/08 – ed. 53). O artigo vai, inclusive, usar o Rhino Mocks.

Enfim, vejam as novas funcionalidades e baixem aqui a nova versão do Rhino Mocks.


Postado na(s) categoria(s) Testes pelo Giovanni Bassi em 30 de junho de 2008 às 01:41 | Tags: ,

Quem é Giovanni Bassi

Giovanni Bassi Sou uma pessoa apaixonada por tecnologia e especificamente por .Net. Sou consultor independente especialista em .Net, focado em arquitetura e melhores práticas. Tenho dezenas de artigos publicados na .Net Magazine, revista da qual sou editor técnico. Ministro palestras e cursos de vez em quando, e quando dá tempo eu respiro um pouco. Mais detalhes nesta página.

Busca

Selos

Eu vou ao TechEd Brasil 2010, e você?

MVP

MCPD

MCSD

.Net Magazine

Abaixo ao if!

Calendário

«  setembro 2010  »
seteququsedo
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910
Ver detalhamento de posts no calendário

Blogs interessantes

    OPMLDownload OPML file

    Postagens recentes

    Comentários recentes

    Disclaimer / Aviso
    As opiniões colocadas neste blog são minhas e pessoais e não expressam necessariamente as opiniões de meus empregadores, pareceiros e amigos. Da mesma forma, os comentários feitos por leitores do blog não expressam a minha opinião.

    © Copyright 2010 .Net Unplugged
    Log in