Skip to content

Instantly share code, notes, and snippets.

@joathan
Created May 19, 2022 17:00
Show Gist options
  • Save joathan/8ef4280f0ec69f096d5a2ddcd74d05f9 to your computer and use it in GitHub Desktop.
Save joathan/8ef4280f0ec69f096d5a2ddcd74d05f9 to your computer and use it in GitHub Desktop.
Testes com falsos positivos

Description

Esse PR é uma Prova de Conceito (POC), com a intenção de validar que estamos usando de forma errada os ambientes de desenvolvimento, teste e produção.

o cenário proposto é utilizar a mesma versão do banco de dados de produção (MySQL 8.0.23), para os ambientes de teste e desenvolvimento, diminuindo assim os falsos positivos nos testes e garantindo que estamos replicando em desenvolvimento o mesmo ambiente que em produção.

Apos rodar os testes usando mesma versão do banco de dados de produção (MySQL 8.0.23), o resultado foi: Finished in 14 minutes 0 seconds (files took 29.77 seconds to load) 3170 examples, 117 failures, 85 pending

Relatório completo em: circleci

Muitos dos erros são: Expression of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'bonuz-api_test.user_credits.expires_at' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

Caso queira rodar um banco com a versão do mysql 8.0.23, pode usar o docker com o seguinte comando: mas antes, certifique-se que seu servidor local esta parado:

brew services stop mysql

Outra configuração importante é; certifique-se que existe essa variável de ambiente no arquivo .env

MYSQL_ROOT_PASSWORD=root

Crie a imagem docker:

docker run --name mysql --platform linux/x86_64 -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql:8.0.28 mysqld --default-authentication-plugin=mysql_native_password

Apos isso, crie o banco de dados em ambiente de teste com o comando:

RAILS_ENV=test rails db:create db:migrate

Com o ambiente de teste configurado, rode o teste:

rspec ./spec/acceptance/api/v1/users_spec.rb:25

O teste irá quebrar, mas na versão do MySQL 5.6.35 isso não ocorre. tornando o teste um falso positivo.

Uma possível solução seria:

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

mas não é uma configuração que seguimos em produção. Captura de Tela 2022-05-19 às 03 13 49

Então, segui com uma mudança ao criar o container MySQL no arquivo de configuração do circleCI, passando os parâmetros:

mysqld --sql_mode="NO_ENGINE_SUBSTITUTION" --default-authentication-plugin=mysql_native_password

O que pode ser feito tbm na imagem do docker com o comando:

docker run --name mysql-no-sql_mode --platform linux/x86_64 -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql:8.0.28 mysqld --default-authentication-plugin=mysql_native_password --sql_mode="NO_ENGINE_SUBSTITUTION"

Mas isso não resolve nosso problema. vejam as imagens após executar o comando:

rspec ./spec/acceptance/internal/api/loyalty/v1/users/report_spec.rb

Captura de Tela 2022-05-19 às 03 46 17 Captura de Tela 2022-05-19 às 03 50 46

O teste quebra pelo fato de que, o que é esperado não esta na mesma ordem do resultado. Observem que é o mesmo resultado, mas que devido ao ORDER BY clause is not in GROUP BY clause and contains nonaggregated ele torna o teste intermitente.

Outro exemplo de um teste tecnicamente correto, mas que devido ao retorno dos dados não estarem em ordem, o teste quebra.

Logo, usar qualquer forma de "mascarar" esse debito técnico, não resolve nosso problema.

A solução definitiva, seria corrigir as querys. para o erro no teste spec/acceptance/internal/api/loyalty/v1/users/report_spec.rb:97 atualizar o arquivo app/services/reports/users/ticket_frequency.rb:22

def purchases
  user.purchases.approved.where(sale_time: @sale_time_range)
      .group("floor(total_value)")
      .order("total_value asc")
      .count(:id)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment