DEV Community

Arthur Fücher for High5Devs

Posted on • Originally published at high5devs.com on

FSCheck: Gerando valores customizados para seu teste de propriedade

Em um outro post, falamos um pouco sobre a utilização do FSCheck para criação de testes de propriedade usando C#. Mostrei os primeiros passos com o FSCheck, e a criação de testes de propriedade bem simples onde nosso teste dependia de um valor _uint p_ara representar uma porcentagem, porém esse tipo de valor pode ser maior do que 100, o que no nosso caso se encaixa muito bem dado que nossa porcentagem seria somente de 0 a 100.

Nesse post iremos nos aprofundar um pouco mais na criação de parâmetros customizáveis, limitando os valores, criando alguns mais específicos e descritivos.


Contexto

No primeiro post que fiz sobre o FSCheck mostrei um contexto de uma aplicação de FlashCards onde testávamos se um cartão tinha sua porcentagem de dificuldade diminuída caso o usuário acertasse a reposta ou se aumentava a dificuldade caso o usuário errasse. O código do nosso exemplo é esse aqui:


[Property]
public Property DeveDiminuirDificuldadeQuandoAcertarAResposta(int porcentagem)
{
 var calculadora = new CalculadoraDeDificuldade();
 var cartão = new Cartão("qlqr pergunta", porcentagem);

 var novoCartão = calculadora.AjustaDificuldade(cartão, true);

 return (novoCartão.Porcentagem < porcentagem).ToProperty();
}

Enter fullscreen mode Exit fullscreen mode

A questão com esse teste é que o valor de porcentagem está variando entre todos os possíveis para uma variável do tipo int, e a nossa propriedade só é válida quando o valor da porcentagem for entre 0 e 100. O FsCheck possui o método When que faz exatamente isso, portanto podemos alterar a criação da nossa propriedade para que fique assim:


return (novoCartão.Porcentagem < porcentagem)
         .ToProperty()
         .When(porcentagem != 0 && porcentagem < 100); 

Enter fullscreen mode Exit fullscreen mode

Utilizando o método When conseguimos limitar o valor do parâmetro porcentagem que será válido para a nossa Propriedade, porém agora todo teste que dependa desse valor teremos que adicionar esse código. O que precisamos é que o FSCheck saiba gerar corretamente os valores, e para isso ele disponibiliza uma maneira de criar os nossos próprios geradores de valores.

Gerando valores customizáveis

Para criar esse valores customizaveis iremos criar uma classe para agrupar os geradores, e esses geradores serão métodos estáticos que retornam um Arbitrary do valor que quer gerar.

O nome do método podemos colocar algo que deixe explícito o retorno.

No nosso caso o tipo que usamos é int, iremos criar um método estatico que irá retornar um Arbitrary de int e iremos dar o nome de Porcentagem.


    public class Tipos
    {
        public static Arbitrary<int> Porcentagem() =>
            Arb.Default.Int32().Generator.
                Where(x => x > 0 && x <= 100).ToArbitrary();
    }

Enter fullscreen mode Exit fullscreen mode

Olhando a implementação acima veja que utilizamos o próprio gerador de int da biblioteca Arb.Default.Int32().Generator e depois usamos um Where para filtrar o intervalo de valores que queremos. E para retornar um Arbitrary basta chamar o método ToArbitrary.

Agora que criamos esse gerador, precisamos fazer indicar para o nosso teste que deve utilizar essa classe como fonte. Conseguimos fazer isso apenas alterando o atributo Property:


[Property(Arbitrary = new[] {typeof(Tipos)})]

Enter fullscreen mode Exit fullscreen mode

Com isso quando o nosso teste solicita uma entrada to tipo int, ele acha o nosso gerador e chama ele ao invés do padrão, com isso nosso código não precisa mais lidar com o tratamento do valor e podemos remover o When que tínhamos colocado.

Olhando nosso código, utilizamos a porcentagem para criar nosso objeto Cartão e usamos ele para fazer o teste. E se, ao invés de receber a porcentagem, nós recebessemos um objeto de Cartão já pronto?

Criando nosso Cartão

Para criar um novo gerador, precisamos alterar nossa classe Tipos, e adicionar agora um novo método que retorne um Arbitrary de Cartão. Nele podemos utilizar o gerador de Porcentagem que criamos e mapear para um Cartão. Veja como fica a implementação:


public static Arbitrary<Cartão> Cartão() =>
  Porcentagem().Generator
    .Select(porcentagem => new Cartão(Arb.Default.String()
                                                 .Generator
                                                 .Sample(20, 1)
                                                 .Single(),
                                      porcentagem))
    .ToArbitrary();

Enter fullscreen mode Exit fullscreen mode

Veja que estamos mapeando uma porcentagem para o nosso Cartão, e utilizamos outro gerador padrão do FSCheck para construir a descrição do cartão de maneira automática também. Agora basta alterar nosso teste para receber um Cartão


        [Property(Arbitrary = new[] {typeof(Tipos)})]
        public Property DeveDiminuirDificuldadeQuandoAcertarAResposta3(Cartão cartão)
        {
          var calculadora = new CalculadoraDeDificuldade();

          var novoCartão = calculadora.AjustaDificuldade(cartão, true);

          return (novoCartão.Porcentagem < cartão.Porcentagem).ToProperty();
        }

Enter fullscreen mode Exit fullscreen mode

Com isso conseguimos construir qualquer objeto nosso com as restrições que precisamos para determinada propriedade, e deixar nosso teste simples e descritivo.

Podemos também criar classes que representem estados dos nossos objetos, como por exemplo um _ CartãoComPorcentagemAcimaDe80 _ que estende o Cartão. Dá para viajar nisso, mas falaremos disso em outro post.

Se quiser dar uma olhada no código, ele está no meu github: fscheck-examples


Eai, o que achou da utilização de geradores customizáveis? Tem dúvidas? Já usou?

Deixe um comentário ?

Abraços

Imagem usada no post Orsolya Vékony em Unsplash

O post FSCheck: Gerando valores customizados para seu teste de propriedade apareceu primeiro em High5Devs.

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay