Fala, galera! Esse é um assunto que não vejo sendo muito discutido entre os QAs que eu converso, mas vocês acham que devem passar Lint no seu projeto de teste? Espero que a resposta tenha sido “sim”.
OBS: Lembrando que isso vale para todos que escrevem pelo menos uma linha de código, até porque QAs que automatizam também são desenvolvedores.
Antes de eu começar, seria interessante saber o que seria o tal do Lint ou, melhor dizendo, análise estática de código, esse vai ser o nome que vamos utilizar daqui em diante.
A análise estática do código nada mais é do que uma depuração do seu código fonte, ou seja, ela faz a busca por possíveis bugs, verifica erros de sintaxe, complexidade ciclomática de código e também é possível perceber a verificação de style code e boas práticas. Existem outras características de análise, mas acredito que essas já te façam olhar o Lint com outros olhos.
E o que eu ganho fazendo uma análise estática do meu código? Um dos principais ganhos é automatizar um processo que é demorado, que requer muita atenção a cada linha que vai ser analisada. Veja o exemplo abaixo:
#!/usr/bin/env ruby class Lint def get_even_numbers numbers_list = [30, 434, 10, 4, 6, 9, 98, 7, 14, 21] for number in numbers_list if number % 2 == 0 puts "Even number", number end end end end
Legal! Temos um pedaço de código que só vai retornar os números pares. Mas, e aí? Conseguem olhar e já saber quais são os problemas desse código?
Para realizar a análise estática de código em Ruby, vou utilizar o RuboCop, que é baseado no Ruby style guide. Esse link ensina como instalar, então vou focar aqui somente em como utilizar e configurar.
Com o Rubocop instalado, vamos rodar para saber o que esse código nos apresenta.
lint.rb:1:1: W: Script file lint.rb doesn't have execute permission. #!/usr/bin/env ruby ^^^^^^^^^^^^^^^^^^^ lint.rb:2:1: C: Missing top-level class documentation comment. class Lint ^^^^^ lint.rb:3:1: C: Use 2 (not 0) spaces for indentation. def get_even_numbers lint.rb:3:5: C: Do not prefix reader method names with get_. def get_even_numbers ^^^^^^^^^^^^^^^^ lint.rb:5:3: C: Prefer each over for. for number in numbers_list ^^^ lint.rb:6:5: C: Favor modifier if usage when having a single-line body. Another good alternative is the usage of control flow &&/||. if number % 2 == 0 ^^ lint.rb:6:8: C: Replace with Integer#even?. if number % 2 == 0 ^^^^^^^^^^^^^^^ lint.rb:6:8: C: Use (number % 2).zero? instead of number % 2 == 0. if number % 2 == 0 ^^^^^^^^^^^^^^^ lint.rb:7:12: C: Prefer single-quoted strings when you don't need string interpolation or special symbols. puts "Even number", number ^^^^^^^^^^^^^ lint.rb:7:26: C: Unnecessary spacing detected. puts "Even number", number ^ 1 Layout/ExtraSpacing 1 Layout/IndentationWidth 1 Lint/ScriptPermission 1 Naming/AccessorMethodName 1 Style/Documentation 1 Style/EvenOdd 1 Style/For 1 Style/IfUnlessModifier 1 Style/NumericPredicate 1 Style/StringLiterals -- 10 Total 1 file inspected, 10 offenses detected
Vocês vão olhar e falar: “Nossa! Como um código tão pequeno pode ter tantos “problemas”?
Sim! É por isso que quando abrimos, por exemplo, o Android Studio ele nos dá, pelo menos, 30k de warnings e possíveis problemas.
Vamos refatorar esse pequeno código problemático, seguindo as boas práticas?
# Lint class class Lint def even_numbers numbers_list = [30, 434, 10, 4, 6, 9, 98, 7, 14, 21] numbers_list.each do |number| puts 'Even number', number if number.even? end end end
Agora vamos rodar novamente o Rubocop:
15:19 $ rubocop lint.rb -f offenses -f clang -- 0 Total
Podemos ver que agora estamos seguindo as boas práticas e nosso Lint não acusa nenhum problema. Um fator importante é que é possível configurar o que vai ser verificado através de um arquivo rubocop.yml, que deve ficar na raiz do seu projeto. Abaixo, segue um exemplo que criei e que venho usando durante um tempo nos projetos que participo:
Documentation: Enabled: false AllCops: Include: - '**/Rakefile' Exclude: - 'step_definitions/**' - 'screenshots/**/*' - '*.feature' - 'reports/**' TargetRubyVersion: 2.3.0 #Lint checks are defined here Lint: Severity: error Lint/AmbiguousBlockAssociation Enabled: true Lint/ConditionPosition Enabled: true Lint/ElseLayout Enabled: true Lint/HandleExceptions Enabled: true Lint/Loop Enabled: true #Style checks are defined here Style/Encoding: EnforcedStyle: when_needed Enabled: true Style/FrozenStringLiteralComment: EnforcedStyle: alway Style/EmptyLinesAroundBlockBody: Enabled: true Style/EmptyLinesAroundModuleBody: Enabled: true Style/AutoResourceCleanup: Enabled: true # Metrics like method length and complexity are defined here Metrics/LineLength: Max: 80 Metrics/CyclomaticComplexity: Enabled: true Metrics/MethodLength: Max: 10 CountComments: false
Temos também um ganho em legibilidade do código. Não é um “Hadouken”, mas mesmo que o código seja pequeno, já iniciamos o processo de “hadoukenização”.
Código Hadouken:
É de extrema importância ressaltar que o Lint não substitui o bom e velho code review, ele apenas automatiza parte do processo e faz isso muito mais rápido do que se você tivesse que olhar linha por linha.
Façam Code Review!
Então, da mesma maneira que o Lint é passado nos projetos de back ou front-end, ele deve ser passado no seu teste.
Mas, por que?
Seu teste automatizado também é código, e por ser código deve seguir as boas práticas da programação e seguir o style de cada linguagem. Fazendo isso, você garante que a pessoa que for pegar o seu código para ler, não dê de cara com um mini monstro, mas sim com um código bonito e fácil de ler.
Nesse exemplo, citei apenas um trecho de código feito em Ruby, mas existem Lints para diversas linguagens. Logo, dá para rodar naquela classe que você acabou de escrever e não se preocupou com a granularidade de seus métodos, nem com a sua complexidade ciclomática e tal.
Espero que este texto sirva de inspiração para que vocês comecem a passar um Lint no código e que isso faça com que evolua para um Lint que rode em uma integração contínua.
***
Este artigo foi publicado originalmente em: https://www.concrete.com.br/2018/01/11/porque-usar-lint-no-seu-projeto-de-testes/