Arranjo de teste usando o sistema em teste

5

Eu tenho alguns testes de integração em torno de procs armazenados. Normalmente eu faço a configuração de teste usando o Dapper. Isso é bom para casos simples, mas em alguns casos para configurar o sistema corretamente, seria muito mais simples chamar os procedimentos armazenados necessários. Seria mais simples, porque algumas entidades têm muitos relacionamentos e restrições, e replicar isso no Dapper é demorado, além disso, se eu alterar o sistema, alterarei meu código de configuração do teste Dapper.

É uma boa idéia usar o sistema para configurar o sistema para testar ou devo manter a configuração do sistema independente do sistema?

Eu adicionei um exemplo de código simples, abaixo, (não representativo do meu sistema atual) para ajudar a esclarecer o que quero dizer. No primeiro teste, estou verificando se CreatePerson realmente adiciona uma entidade à tabela Person. No segundo teste eu uso o método que acabei de testar, CreatePerson, para configurar o sistema e depois testar outra coisa.

public class When_CreatePerson_is_called
{
    [Fact]
    public void It_should_create_entity()
    {
        // arrange
        var db = new Database();

        // act - testing CreatePerson does what is expected of it
        int id = db.CreatePerson();
        Person p = db.GetPerson(id);

        Assert.NotNull(p);
    }
}

public class When_UpdatePerson_is_called
{
    [Fact]
    public void It_should_update_untity()
    {
        // arrange
        var db = new Database();
        int id = db.CreatePerson(); // Should I use a different way to initialize the system or is it ok to use the system?

        // act
        db.UpdatePerson(id, "John Smith");
        Person p = db.GetPerson(id);

        Assert.Equal("John Smith", p.FullName);
    }
}
    
por andygjp 21.05.2016 / 19:25
fonte

2 respostas

3

Em qualquer teste, isso pode ser bom ou ruim. O mais provável é que você possa escrever este teste, e é bom ter um teste que execute o CreatePerson real junto com o% realUpdatePerson.

Em geral, o fato de você poder usar um código de produção nos testes já é bom. Deverá haver absolutamente testes que exercitem todo o seu código de produção, mas se duas partes do código de produção devem ser testadas juntas ou separadamente é muito mais difícil de dizer.

Quando você achar difícil escrever um teste que use apenas um método no código de produção, sem chamar outros métodos ao redor, isso geralmente significa um dos seguintes:

  1. Devido à forma como a API funciona, não faz sentido chamar esse método isoladamente, por isso é perfeitamente adequado para nenhum dos testes chamá-lo de forma isolada. Por exemplo, quase todos os testes em um método dbConnection.executeQuery() terão que chamar database.makeConnection() . É assim que funcionam os bancos de dados.

  2. Seus métodos são excessivamente acoplados uns aos outros, e há uma oportunidade de refatorar as coisas de uma maneira que tornaria os testes e o código de produção mais fáceis de escrever.

Para o exemplo específico que você deu, # 1 parece muito mais provável para mim. Simplesmente não faz sentido atualizar uma pessoa que ainda nem existe, então no código de produção ninguém nunca vai chamar UpdatePerson sem primeiro chamar CreatePerson (senão eles recebem um erro ... que você deve ter outro teste para).

Um teste decisivo útil para ajudar a decidir é considerar o que esses dois testes diferentes estão dizendo sobre sua API pública. Se você escrever um teste que chame UpdatePerson em um banco de dados falso pré-preenchido, você está dizendo que UpdatePerson deve sempre assumir essa estrutura de banco de dados específica , mesmo que tenha sido criada por alguma outra API. Se você escrever um teste que chama UpdatePerson depois de chamar CreatePerson , você está dizendo que UpdatePerson deve sempre retornar o que foi passado para CreatePerson , não importando como foi armazenado . Qual desses sons é mais correto para o seu projeto?

    
por 21.05.2016 / 19:57
fonte
2

É perfeitamente correto usar o código de produção para seus testes, desde que você não faça um curto circuito no teste. Por exemplo, não faça isso:

var expected = 4;
var actual = Calc.Subtract(Calc.Add(expected, 1));
Assert.AreEqual(expected, actual);

Desde que você saiba que o teste falha quando algo está errado, acho que é ainda melhor reutilizar o código de produção para configurações de teste.

    
por 21.05.2016 / 19:37
fonte