DEV Community

Silvair L. Soares
Silvair L. Soares

Posted on

Usando o chat do Bing como um aliado para escrever testes de software

Image description

Imagem gerada com a ferramenta Criador de Imagens do Bing.

A criação de testes é uma parte crucial do processo de desenvolvimento de software. Pois garante que o software funcione corretamente e atenda às expectativas dos usuários.

No entanto, um desafio enfrentado pelos desenvolvedores é obter dados falsos e aleatórios para serem usados nestes testes. Dados falsos são necessários para simular cenários realistas e garantir que o software seja capaz de lidar com diferentes situações.

Para auxiliar na geração de dados falsos para os testes, existe uma excelente biblioteca chamada Bogus, disponível nesse repositório do Nuget.

Esta biblioteca auxilia na geração de instâncias de dados fakes, de acordo com as classes do seu projeto.

Um pequeno exemplo:

 public class NotaFiscal

    public long Id { get; set; }
    public int Operacao { get; set; }
    public string TipoEmissao { get; set; }
    public string ModeloDocumento { get; set; }
    public string Situacao { get; set; }
    public int Serie { get; set; }
    public int Numero { get; set; }
    public DateTime DataEmissao { get; set; }
    public DateTime DataEntradaSaida { get; set; } 
}
Enter fullscreen mode Exit fullscreen mode

Para gerar uma instância fake da classe NotaFiscal, poderíamos fazer o seguinte código usando o Bogus:

using Bogus;

namespace Exemplo
{
    public class NotaFiscalFaker : Faker<NotaFiscal>
    {
        public NotaFiscalFaker()
        {
            RuleFor(n => n.Id, f => f.Random.Long(1));
            RuleFor(n => n.Operacao, f => f.Random.Int(1));
            RuleFor(n => n.TipoEmissao, f => f.Random.String2(10));
            RuleFor(n => n.ModeloDocumento, f => f.Random.String2(10));
            RuleFor(n => n.Situacao, f => f.Random.String2(10));
            RuleFor(n => n.Serie, f => f.Random.Int(1));
            RuleFor(n => n.Numero, f => f.Random.Int(1));
            RuleFor(n => n.DataEmissao, f=>f.Date.Recent());
            RuleFor(n=>n.DataEntradaSaida,f=>f.Date.Recent());
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Você pode usar esse builder da seguinte maneira:

var faker = new NotaFiscalFaker();
var fakeNotaFiscal = faker.Generate();
Enter fullscreen mode Exit fullscreen mode

Com este pequeno exemplo, dá pra perceber que o Bogus, é uma mão-na-roda. Mas imagine um cenário em que tenhamos centenas de classes de dados extensas, daria um trabalhão, gerar um builder para cada uma dessas classes. Manter esses builders, à medida que estas classes vão sendo evoluídas, também dará um trabalho extra.

O Chat do novo Bing, pode nos ajudar com este trabalho braçal e maçante.

Abaixo, descrevo minha conversa com o Chat do Bing, e mostro o excelente resultado que ele me deu, durante a geração de builders, para as seguintes classes em c#:

NotaFiscal:

public class NotaFiscal
{
    public long Id { get; set; }

    /// <summary> 
    /// IND_OPER - Indicador do tipo de operação:
    /// 
    /// <para>0 - Entrada</para> 
    /// <para>1 - Saída</para> 
    /// </summary> 
    public int Operacao { get; set; }

    /// <summary> 
    /// IND_EMIT - Indicador do emitente do documento fiscal:
    /// 
    /// <para>0 - Emissão própria</para> 
    /// <para>1 - Terceiros</para> 
    /// </summary> 
    public string TipoEmissao { get; set; }

    public NotaFiscalProdutoNaturezaOperacao NaturezaOperacao { get; set; }

    public Participante Participante { get; set; }

    public string ModeloDocumento { get; set; }

    public string Situacao { get; set; }

    public int Serie { get; set; }

    public int Numero { get; set; }

    public string Chave { get; set; }

    public DateTime DataEmissao { get; set; }

    public DateTime DataEntradaSaida { get; set; }

    public decimal ValorTotal { get; set; }

    public int TipoPagamento { get; set; }

    public decimal ValorDesconto { get; set; }

    public decimal ValorAbatimento { get; set; }

    public decimal ValorMercadorias { get; set; }

    public int TipoTransporte { get; set; }

    public decimal ValorFrete { get; set; }

    public decimal ValorSeguro { get; set; }

    public decimal ValorDespesas { get; set; }

    public decimal ICMS_BC { get; set; }

    public decimal ICMS_Aliquota { get; set; }

    public decimal ICMS_Valor { get; set; }

    public decimal ICMS_ST_BC_Valor { get; set; }

    public decimal ICMS_ST_Retido_Valor { get; set; }

    public decimal IPI_Valor { get; set; }

    public decimal PIS_Valor { get; set; }

    public decimal PIS_ST_Valor { get; set; }

    public decimal COFINS_Valor { get; set; }

    public decimal COFINS_ST_Valor { get; set; }

    public List<NotaFiscalProduto> Produtos { get; set; }

}
Enter fullscreen mode Exit fullscreen mode

Participante:

public class Participante
{
    public long Id { get; set; }
    public string Codigo { get; set; }
    public string Nome { get; set; }
    public string Cod_Pais { get; set; }
    public string CNPJ { get; set; }
    public string CPF { get; set; }
    public string IE { get; set; }
    public string SUFRAMA { get; set; }
    public string EnderecoCod_Mun { get; set; }
    public string EnderecoLogradouro { get; set; }
    public string EnderecoNumero { get; set; }
    public string EnderecoComplemento { get; set; }
    public string EnderecoBairro { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Produto:

public class Produto
{
    public long Id { get; set; }
    public string Codigo { get; set; }
    public string Descricao { get; set; }
    public NotaFiscalProdutoUnidade Unidade { get; set; }
    public int Origem { get; set; }
    public string NCM { get; set; }
    public string CEST { get; set; }
    public decimal ICMS_Aliquota { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

NotaFiscalProduto:

public class NotaFiscalProduto
{
    public long NotaFiscalId { get; set; }
    public int Numero { get; set; }
    public Produto Produto { get; set; }
    public decimal Quantidade { get; set; }
    public decimal ValorTotal { get; set; }
    public decimal Desconto { get; set; }
    public int Movimentado { get; set; }
    public string ICMS_CST { get; set; }
    public string CFOP { get; set; }
    public decimal ICMS_BC { get; set; }
    public decimal ICMS_Aliquota { get; set; }
    public decimal ICMS_Valor { get; set; }
    public decimal ICMS_ST_BC { get; set; }
    public decimal ICMS_ST_Aliquota { get; set; }
    public decimal ICMS_ST_Valor { get; set; }
    public int IPI_Apuracao { get; set; }
    public string IPI_CST { get; set; }
    public string IPI_Enquadramento { get; set; }
    public decimal IPI_BC { get; set; }
    public decimal IPI_Aliquota { get; set; }
    public decimal IPI_Valor { get; set; }
    public string PIS_CST { get; set; }
    public decimal PIS_BC { get; set; }
    public decimal PIS_Aliquota { get; set; }
    public decimal PIS_BC_Quantidade { get; set; }
    public decimal PIS_Aliquota_Reais { get; set; }
    public decimal PIS_Valor { get; set; }
    public string COFINS_CST { get; set; }
    public decimal COFINS_BC { get; set; }
    public decimal COFINS_Aliquota { get; set; }
    public decimal COFINS_BC_Quantidade { get; set; }
    public decimal COFINS_Aliquota_Reais { get; set; }
    public decimal COFINS_Valor { get; set; }
    public string ContaContabil { get; set; }
    public decimal ValorAbatimento { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

NotaFiscalProdutoUnidade:

public class NotaFiscalProdutoUnidade
{
    public long Id { get; set; }
    public string Codigo { get; set; }
    public string Simbolo { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

NotaFiscalProdutoNaturezaOperacao:

public class NotaFiscalProdutoNaturezaOperacao
{
    public long Id { get; set; }
    public string Codigo { get; set; }
    public string Descricao { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Abaixo, a transcrição da minha conversa com o chat do Bing:

Meu prompt:

1 - Usando a biblioteca Bogus para .Net, gere um builder para criar instâncias fakes da classe "NotaFiscalProdutoNaturezaOperacao".

Resposta do Chat:

Image description

Então segui, com os seguintes prompts:

2 - Usando a biblioteca Bogus para .Net, gere um builder para criar instâncias fakes da classe "NotaFiscalProdutoUnidade".

3 - Usando a biblioteca Bogus para .Net, gere um builder para criar instâncias fakes da classe "NotaFiscalProduto".

4 - Usando a biblioteca Bogus para .Net, gere um builder para criar instâncias fakes da classe "Produto".

5 - Usando a biblioteca Bogus para .Net, gere um builder para criar instâncias fakes da classe "Participante".

Neste momento, algo interessante ocorreu: Eu esqueci de informar para o chat do Bing, a definição da classe Participante:

Image description

6 - Usando a biblioteca Bogus para .Net, gere um builder para criar instâncias fakes da classe "NotaFiscal".

Em alguns minutos, consegui criar os builders para todo o modelo de dados da API:

Image description

Obtendo como resultado as seguintes classes:

NotaFiscalProdutoNaturezaOperacaoFaker

public class NotaFiscalProdutoNaturezaOperacaoFaker : Faker<NotaFiscalProdutoNaturezaOperacao>
{
    public NotaFiscalProdutoNaturezaOperacaoFaker()
    {
        RuleFor(n => n.Id, f => f.Random.Long(1));
        RuleFor(n => n.Codigo, f => f.Random.String2(10));
        RuleFor(n => n.Descricao, f => f.Lorem.Sentence());
    }
}
Enter fullscreen mode Exit fullscreen mode

NotaFiscalProdutoUnidadeFaker

public class NotaFiscalProdutoUnidadeFaker : Faker<NotaFiscalProdutoUnidade>
{
    public NotaFiscalProdutoUnidadeFaker()
    {
        RuleFor(n => n.Id, f => f.Random.Long(1));
        RuleFor(n => n.Codigo, f => f.Random.String2(10));
        RuleFor(n => n.Simbolo, f => f.Random.String2(3));
    }
}
Enter fullscreen mode Exit fullscreen mode

NotaFiscalProdutoFaker

public NotaFiscalProdutoFaker()
{
    RuleFor(n => n.NotaFiscalId, f => f.Random.Long(1));
    RuleFor(n => n.Numero, f => f.Random.Int(1));
    RuleFor(n => n.Produto, f => new ProdutoFaker().Generate());
    RuleFor(n => n.Quantidade, f => f.Random.Decimal(1));
    RuleFor(n => n.ValorTotal, f => f.Random.Decimal(1));
    RuleFor(n => n.Desconto, f => f.Random.Decimal(1));
    RuleFor(n => n.Movimentado, f => f.Random.Int(1));
    RuleFor(n => n.ICMS_CST, f => f.Random.String2(10));
    RuleFor(n => n.CFOP, f => f.Random.String2(10));
    RuleFor(n => n.ICMS_BC, f => f.Random.Decimal(1));
    RuleFor(n => n.ICMS_Aliquota, f => f.Random.Decimal(1));
    RuleFor(n => n.ICMS_Valor, f => f.Random.Decimal(1));
    RuleFor(n => n.ICMS_ST_BC, f => f.Random.Decimal(1));
    RuleFor(n => n.ICMS_ST_Aliquota, f => f.Random.Decimal(1));
    RuleFor(n => n.ICMS_ST_Valor, f => f.Random.Decimal(1));
    RuleFor(n => n.IPI_Apuracao, f => f.Random.Int(1));
    RuleFor(n => n.IPI_CST, f => f.Random.String2(10));
    RuleFor(n => n.IPI_Enquadramento, f => f.Random.String2(10));
    RuleFor(n => n.IPI_BC, f => f.Random.Decimal(1));
    RuleFor(n => n.IPI_Aliquota, f => f.Random.Decimal(1));
    RuleFor(n => n.IPI_Valor, f => f.Random.Decimal(1));
    RuleFor(n => n.PIS_CST, f => f.Random.String2(10));
    RuleFor(n => n.PIS_BC, f => f.Random.Decimal(1));
    RuleFor(n => n.PIS_Aliquota, f => f.Random.Decimal(1));
    RuleFor(n => n.PIS_BC_Quantidade, f => f.Random.Decimal(1));
    RuleFor(n => n.PIS_Aliquota_Reais, f => f.Random.Decimal(1));
    RuleFor(n => n.PIS_Valor, f => f.Random.Decimal(1));
    RuleFor(n => n.COFINS_CST, f => f.Random.String2(10));
    RuleFor(n => n.COFINS_BC, f => f.Random.Decimal(1));
    RuleFor(n => n.COFINS_Aliquota, f => f.Random.Decimal(1));
    RuleFor(n => n.COFINS_BC_Quantidade, f => f.Random.Decimal(1));
    RuleFor(n => n.COFINS_Aliquota_Reais, f => f.Random.Decimal(1));
    RuleFor(n => n.COFINS_Valor, f => f.Random.Decimal(1));
}
Enter fullscreen mode Exit fullscreen mode

ProdutoFaker

public class ProdutoFaker : Faker<Produto>
{
    public ProdutoFaker()
    {
        RuleFor(n => n.Id, f => f.Random.Long(1));
        RuleFor(n => n.Codigo, f => f.Random.String2(10));
        RuleFor(n => n.Descricao, f => f.Lorem.Sentence());
        RuleFor(n => n.Unidade, f => new NotaFiscalProdutoUnidadeFaker().Generate());
        RuleFor(n => n.Origem, f => f.Random.Int(1));
        RuleFor(n => n.NCM, f => f.Random.String2(10));
        RuleFor(n => n.CEST, f => f.Random.String2(10));
        RuleFor(n => n.ICMS_Aliquota, f => f.Random.Decimal(1));
    }
}
Enter fullscreen mode Exit fullscreen mode

ParticipanteFaker

public class ParticipanteFaker : Faker<Participante>
{
    public ParticipanteFaker()
    {
        RuleFor(n => n.Id, f => f.Random.Long(1));
        RuleFor(n => n.Codigo, f => f.Random.String2(10));
        RuleFor(n => n.Nome, f => f.Name.FullName());
        RuleFor(n => n.Cod_Pais, f => f.Address.CountryCode());
        RuleFor(n => n.CNPJ, f => f.Company.Cnpj());
        RuleFor(n => n.CPF, f => f.Person.Cpf());
        RuleFor(n => n.IE, f => f.Random.String2(10));
        RuleFor(n => n.SUFRAMA, f => f.Random.String2(10));
        RuleFor(n => n.EnderecoCod_Mun, f => f.Random.String2(10));
        RuleFor(n => n.EnderecoLogradouro, f => f.Address.StreetName());
        RuleFor(n => n.EnderecoNumero, f => f.Address.BuildingNumber());
        RuleFor(n => n.EnderecoComplemento, f => f.Address.SecondaryAddress());
        RuleFor(n => n.EnderecoBairro, f => f.Address.County());
    }
}
Enter fullscreen mode Exit fullscreen mode

NotaFiscalFaker

public class NotaFiscalFaker : Faker<NotaFiscal>
{
    public NotaFiscalFaker()
    {
        RuleFor(n => n.Id, f => f.Random.Long(1));
        RuleFor(n => n.Operacao, f => f.PickRandom(new int[] { 0, 1 }));
        RuleFor(n => n.TipoEmissao, f => f.PickRandom(new string[] { "0", "1" }));
        RuleFor(n => n.NaturezaOperacao, f => new NotaFiscalProdutoNaturezaOperacaoFaker().Generate());
        RuleFor(n => n.Participante, f => new ParticipanteFaker().Generate());
        RuleFor(n => n.ModeloDocumento, f => f.Random.String2(10));
        RuleFor(n => n.Situacao, f => f.Random.String2(10));
        RuleFor(n => n.Serie, f => f.Random.Int(1));
        RuleFor(n => n.Numero, f => f.Random.Int(1));
        RuleFor(n => n.Chave, f => f.Random.String2(10));
        RuleFor(n => n.DataEmissao, f => f.Date.Recent());
        RuleFor(n => n.DataEntradaSaida, f => f.Date.Recent());
        RuleFor(n => n.ValorTotal, f => f.Random.Decimal(1));
        RuleFor(n => n.TipoPagamento, f => f.Random.Int(1));
        RuleFor(n => n.ValorDesconto, f => f.Random.Decimal(1));
        RuleFor(n => n.ValorAbatimento, f => f.Random.Decimal(1));
        RuleFor(n => n.ValorMercadorias, f => f.Random.Decimal(1));
        RuleFor(n => n.TipoTransporte, f => f.Random.Int(1));
        RuleFor(n => n.ValorFrete, f => f.Random.Decimal(1));
        RuleFor(n => n.ValorSeguro, f => f.Random.Decimal(1));
        RuleFor(n => n.ValorDespesas, f => f.Random.Decimal(1));
        RuleFor(n => n.ICMS_BC, f => f.Random.Decimal(1));
        RuleFor(n => n.ICMS_Aliquota, f => f.Random.Decimal(1));
        RuleFor(n => n.ICMS_Valor, f => f.Random.Decimal(1));
        RuleFor(n => n.ICMS_ST_BC_Valor, f => f.Random.Decimal(1));
        RuleFor(n => n.ICMS_ST_Retido_Valor, f => f.Random.Decimal(1));
        RuleFor(n => n.IPI_Valor, f => f.Random.Decimal(1));
        RuleFor(n => n.PIS_Valor, f => f.Random.Decimal(1));
        RuleFor(n => n.PIS_ST_Valor, f => f.Random.Decimal(1));
        RuleFor(n => n.COFINS_Valor, f => f.Random.Decimal(1));
        RuleFor(n => n.COFINS_ST_Valor, f => f.Random.Decimal(1));
        RuleFor(n => n.Produtos, f => new NotaFiscalProdutoFaker().Generate(f.Random.Int(5)));
    }
}
Enter fullscreen mode Exit fullscreen mode

Repare que ele entendeu os comentários das propriedades da classe NotaFiscal:

/// <summary> 
/// IND_OPER - Indicador do tipo de operação:
/// 
/// <para>0 - Entrada</para> 
/// <para>1 - Saída</para> 
/// </summary> 
public int Operacao { get; set; }

/// <summary> 
/// IND_EMIT - Indicador do emitente do documento fiscal:
/// 
/// <para>0 - Emissão própria</para> 
/// <para>1 - Terceiros</para> 
/// </summary> 
public string TipoEmissao { get; set; }
Enter fullscreen mode Exit fullscreen mode

Fazendo a personalização dos valores que podem ser incluidos nestas propridades:

RuleFor(n => n.Operacao, f => f.PickRandom(new int[] { 0, 1 }));

RuleFor(n => n.TipoEmissao, f => f.PickRandom(new string[] { "0", "1" }));
Enter fullscreen mode Exit fullscreen mode

Com estas classes geradas, ao escrever os testes unitários, ou até os testes de integração, sempre que precisar de uma instância com dados totalmente randômicos destas classes, tudo que tenho a fazer é invocar os builders, assim:

var faker = new NotaFiscalProdutoNaturezaOperacaoFaker();
var fakeNotaFiscalProdutoNaturezaOperacao = faker.Generate();
Enter fullscreen mode Exit fullscreen mode
var faker = new NotaFiscalProdutoNaturezaOperacaoFaker();
var fakeNotaFiscalProdutoNaturezaOperacao = faker.Generate();
Enter fullscreen mode Exit fullscreen mode
var faker = new NotaFiscalProdutoUnidadeFaker();
var fakeNotaFiscalProdutoUnidade = faker.Generate();
Enter fullscreen mode Exit fullscreen mode
var faker = new NotaFiscalProdutoFaker();
var fakeNotaFiscalProduto = faker.Generate();
Enter fullscreen mode Exit fullscreen mode
var faker = new ProdutoFaker();
var fakeProduto = faker.Generate();
Enter fullscreen mode Exit fullscreen mode
var faker = new ParticipanteFaker();
var fakeParticipante = faker.Generate();
Enter fullscreen mode Exit fullscreen mode
var faker = new NotaFiscalFaker();
var fakeNotaFiscal = faker.Generate();
Enter fullscreen mode Exit fullscreen mode

Não é objetivo deste artigo, mostrar como criar os testes, o objetivo aqui foi somente mostrar como as inteligências artificiais, podem nos ajudar a fazer o trabalho chato e altamente suscetível à erros, de forma automática. Tudo que você precisa fazer é fornecer um contexto e caprichar nos prompts.

Top comments (0)