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.
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
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