86 votes

Rubocop 25 lignes de taille de bloc et tests RSpec

Un test unitaire RSpec typique fait un usage intensif de blocs Ruby imbriqués afin de structurer le code et d'utiliser la "magie" DSL pour que les spécifications soient lues comme des déclarations BDD :

describe Foo do
  context "with a bar" do
    before :each do
      subject { Foo.new().add_bar }
    end

    it "looks like a baz" do
      expect # etc

Dans une spécification idéale, chaque exemple peut être relativement court et précis. Cependant, il semble habituel que les blocs extérieurs atteignent plus de 100 lignes, parce que la structure RSpec fonctionne de cette façon, et qu'il ne faut pas beaucoup d'exemples de spécifications, dont chacun peut avoir quelques lignes de configuration spécifique, pour arriver à describe des blocs de taille égale ou supérieure au code du sujet décrit.

Une récente mise à jour de Rubocop a introduit une nouvelle règle, selon laquelle les blocs ne doivent pas dépasser 25 lignes. Je ne suis pas sûr de la raison de cette règle, car elle n'est pas mentionnée dans le manuel de Rubocop. Guide de style Ruby . Je peux voir pourquoi cela pourrait être une bonne chose, et ajouté aux règles par défaut. Cependant, après la mise à jour, notre test Rubocop échoue à plusieurs reprises avec des messages tels que tests/component_spec.rb:151:3: C: Block has too many lines. [68/25]

Avec des outils de mesure du code tels que Rubocop, j'ai comme d'avoir une politique de "Utiliser les valeurs par défaut, faire un lien vers le guide de style, travail terminé". (principalement parce que débattre des tabulations ou des espaces et d'autres minuties est une perte de temps, et que, selon l'EMI, il n'y a pas d'autre solution. jamais est résolu) Ici, ce n'est clairement pas possible, deux de nos principaux outils de qualité des données sont en désaccord sur l'approche de la disposition du code - ou du moins c'est ainsi que j'interprète les résultats, je ne vois rien d'intrinsèquement mauvais dans la façon dont nous avons écrit les spécifications.

En réponse, nous avons simplement fixé la règle de la taille des blocs Rubocop à un seuil élevé. Mais cela m'amène à me demander : qu'est-ce que je rate ? RSpec utilise-t-il une approche désormais discréditée pour l'agencement du code, et qu'est-ce que cela signifie ? raisonnable Est-ce que je dois réduire la taille des blocs dans nos tests RSpec ? Je vois des moyens de restructurer le code pour éviter les gros blocs, mais il s'agit sans exception de vilains bidouillages destinés uniquement à satisfaire la règle de Rubocop, par exemple en décomposant tous les blocs en fonctions d'aide :

def looks_like_a_baz
  it "looks like a baz" do
         expect # etc
  end
end

def bar_context
  context "with a bar" do
    before :each do
      subject { Foo.new().add_bar }
    end
    looks_like_a_baz
  end
end

describe Foo do
  bar_context
  # etc

. . . Je veux dire, c'est faisable, mais transformer des tas d'exemples de spécifications en fonctions d'aide de cette manière semble être à l'opposé de l'approche lisible encouragée par la conception de RSpec.

Y a-t-il autre chose que je puisse faire que de trouver des moyens de l'ignorer ?


La question existante la plus proche de ce sujet que j'ai pu trouver ici était la suivante RSpec & Rubocop / Ruby Style Guide et cela semblait pouvoir être résolu en modifiant les modèles de test.

3 votes

El paramètres par défaut d'excl excl exclure des fichiers sous spec/ .

1 votes

@Stefan : Ah, donc notre utilisation de test/ nous a exposé à cela c'est bon à savoir. Cela signifie que les auteurs de Rubocop reconnaissent qu'il y a quelque chose de différent pour le code RSpec, et nous devrions en faire autant.

170voto

J. Willette Points 894

Si un bloc spécifique est généralement trop long, je le spécifie plutôt que les fichiers

Metrics/BlockLength:
  IgnoredMethods: ['describe', 'context']

10 votes

Le fait de dépendre du nom du bloc plutôt que du nom du fichier est plus exact, donc je pense que cette réponse est meilleure.

7 votes

ExcludedMethods a été renommé en IgnoredMethods

99voto

Drenmi Points 6222

Une récente mise à jour de Rubocop a introduit une nouvelle règle, selon laquelle les blocs ne doivent pas dépasser 25 lignes. Je ne suis pas sûr de la raison de cette règle, car elle ne figure pas dans le guide de style Ruby.

Autrefois, tous les policiers étaient basés sur le Ruby Style Guide, et RuboCop était un moyen d'adhérer aux pratiques définies par la communauté.

Les choses ont changé depuis, et la portée de RuboCop s'est élargie pour aider les développeurs à assurer la cohérence de leurs bases de code en général. Cela a conduit à deux choses :

  1. Les flics (même ceux basés sur le Ruby Style Guide) sont maintenant principalement configurables.
  2. Il existe des copies pour des choses qui ne sont pas mentionnées dans le Ruby Style Guide, mais qui sont néanmoins utiles pour assurer la cohérence d'un projet.

Ce flic fait partie de la deuxième catégorie.

RSpec utilise-t-il une approche désormais discréditée pour la disposition du code, et quelles options raisonnables ai-je pour réduire la taille des blocs dans nos tests RSpec ?

La réponse courte est non. Les DSL sont toujours cool :-)

Cette copie est destinée aux gros blocs au sens de la programmation impérative. En tant que guide général, il ne s'applique pas aux DSL, qui sont souvent déclaratifs. Par exemple, avoir un long routes.rb dans Rails est parfaitement bénin. C'est juste le résultat naturel d'une grande application, plutôt qu'une violation du style. (Et avoir beaucoup de tests est purement génial).

Maintenant, RuboCop est assez intelligent, mais il ne sait pas ce qui est un DSL ou non, donc nous ne pouvons pas les ignorer automatiquement. On pourrait argumenter que nous pourrions exclure les méthodes d'entrée DSL des frameworks populaires, comme les routes Rails et les spécifications RSpec. Les raisons de ne pas le faire sont principalement :

  1. Faux négatifs. Toute classe peut implémenter une méthode, en prenant un bloc, avec le même nom.
  2. RuboCop est un outil d'analyse Ruby, et ne devrait pas vraiment connaître les bibliothèques externes. (A l'exception de la /spec est une courtoisie jusqu'à ce que nous ayons un système d'extension adéquat, et cela peut être géré par le répertoire rubocop-rspec gemme.)

Je veux dire, c'est faisable, mais transformer des tas d'exemples de spécifications en fonctions d'aide de cette manière semble être à l'opposé de l'approche lisible encouragée par la conception de RSpec.

L'essentiel est que : RuboCop est là pour nous aider à écrire un meilleur code. Si la conception de notre application est par ailleurs saine, et que nous nous surprenons à rendre les choses moins lisibles simplement pour faire plaisir à RuboCop, alors nous devrions filtrer, configurer, ou désactiver le flic :-)

En réponse, nous avons simplement fixé la règle de la taille des blocs Rubocop à un seuil élevé. Mais cela m'amène à me demander : qu'est-ce que je rate ?

Il s'agit d'un outil plutôt brutal et, comme vous le laissez entendre, vous aurez probablement quelques faux négatifs à cause de lui. Il y a deux types de faux positifs pour ce flic :

  1. Les fichiers qui contiennent des DSL purement déclaratifs, par exemple les routes Rails, les spécifications RSpec.
  2. Les fichiers qui ont un DSL déclaratif mélangé à du code principalement impératif, par exemple un aasm déclaration de la machine à états dans un modèle Rails.

Dans le premier cas, la meilleure solution consiste à exclure le fichier ou le répertoire, et dans le second à utiliser une désactivation en ligne.

Dans votre cas, vous devez mettre à jour votre .rubocop.yml avec :

Metrics/BlockLength:
  Exclude:
    - 'Rakefile'
    - '**/*.rake'
    - 'test/**/*.rb'

(Notez que vous devez réitérer les exclusions de base de la configuration par défaut, car la liste sera écrasée).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X