Back-End

24 jan, 2018

Porque usar Lint no seu projeto de testes

Publicidade

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:

Fonte

É 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/