64 votes

Quelle est la différence entre le sujet et la let de RSpec? Quand doivent-ils être utilisés ou non?

http://betterspecs.org/#subject a quelques infos à propos de subject et let. Cependant, je suis toujours dans le flou sur la différence entre eux. En outre, le post qu'est-Ce que l'argument contre l'utilisation de la avant de, que et soumis à des tests RSpec? dit qu'il est préférable de ne pas utiliser subject ou let. Où irai-je? Je suis tellement confus.

138voto

Dave Schweisguth Points 5138

Résumé: RSpec de l'objet est une variable spéciale qui se réfère à l'objet testé. Les attentes peuvent être définies de manière implicite, qui prend en charge une ligne exemples. Il est clair pour le lecteur, dans certains idiomatiques cas, mais il est par ailleurs difficile à comprendre, et devrait être évitée. De RSpec let variables sont juste paresseusement instancié (memoized) variables. Ils ne sont pas aussi difficile à suivre, car le sujet, mais elle peut encore conduire à des enchevêtrements de tests et doit donc être utilisé avec discrétion.

Le sujet

Comment ça marche

Le sujet est l'objet testé. RSpec a une idée explicite de l'objet. Il peut ou peut ne pas être défini. Si elle l'est, RSpec peut appeler des méthodes sur elle sans la nommer explicitement.

Par défaut, si le premier argument d'une ultrapériphériques exemple de groupe (describe ou context block) est une classe, RSpec crée une instance de cette classe et l'attribue à l'objet. Par exemple, les passes suivants:

class A
end

describe A do
  it "is instantiated by RSpec" do
    expect(subject).to be_an(A)
  end
end

Vous pouvez définir le sujet vous-même avec subject:

describe "anonymous subject" do
  subject { A.new }
  it "has been instantiated" do
    expect(subject).to be_an(A)
  end
end

Vous pouvez donner à l'objet un nom lorsque vous définir:

describe "named subject" do
  subject(:a) { A.new }
  it "has been instantiated" do
    expect(a).to be_an(A)
  end
end

Même si vous avez le nom de l'objet, vous pouvez toujours vous y référer de façon anonyme:

describe "named subject" do
  subject(:a) { A.new }
  it "has been instantiated" do
    expect(subject).to be_an(A)
  end
end

Vous pouvez définir plus d'un nommé sujet. Plus récemment défini nommé le sujet est l'anonyme subject.

Cependant, le sujet est défini,

  1. Il est instancié paresseusement. C'est, de l'implicite à l'instanciation de la description de la classe ou de l'exécution d'un bloc transmis subject n'arrive pas jusqu' subject ou le nom sujet est fait référence dans un exemple. Si vous voulez que votre explicit sujet pour être instancié avec impatience (avant un exemple dans son groupe de pistes), dire subject! au lieu de subject.

  2. Les attentes peuvent être définies implicitement (sans écrire subject ou le nom d'un nommé sous réserve):

    describe A do
      it { is_expected.to be_an(A) }
    end
    

    Le sujet existe à l'appui de cette syntaxe de la ligne.

Quand l'utiliser

Implicite subject (déduite à partir de l'exemple du groupe) est difficile à comprendre, parce que

  • Il est instancié en coulisses.
  • Si elle est utilisée implicitement (en appelant is_expected sans explicite récepteur) ou explicitement (comme subject), il donne au lecteur aucune information sur le rôle ou de la nature de l'objet sur lequel on s'attend à ce que l'on appelle.
  • Le one-liner exemple de syntaxe n'est pas un exemple de description (l'argument de la chaîne d' it dans l'exemple normal de la syntaxe), de sorte que les seules informations que le lecteur a sur le but de l'exemple est l'attente elle-même.

Par conséquent, c'est seulement utile pour l'utilisation implicite de l'objet lorsque le contexte est susceptible d'être bien compris par tous les lecteurs et il n'y a vraiment pas besoin d'un exemple de description. Le procès canonique est de tester ActiveRecord des validations avec shoulda de rapprochement:

describe Article do
  it { is_expected.to validate_presence_of(:title) }
end

Un explicit anonyme subject (défini avec subject sans nom) est un peu mieux, parce que le lecteur peut voir comment il est instancié, mais

  • il peut tout de même mettre l'instanciation de l'objet loin de l'endroit où il est utilisé (par exemple, au-dessus d'un exemple de groupe avec de nombreux exemples d'utilisation), ce qui est toujours difficile à suivre, et
  • il a d'autres problèmes que l'implicite n'est.

Un nom de sujet fournit une intention de révéler son nom, mais la seule raison d'utiliser un nom de sujet au lieu de let variable est si vous voulez utiliser l'anonyme sous réserve de temps en temps, et nous avons expliqué pourquoi l'anonyme sujet est difficile à comprendre.

Ainsi, les usages légitimes de l'explicite anonyme subject ou un nom de sujet sont très rares.

let variables

Comment ils fonctionnent

let variables sont comme nommé sujets à deux différences près:

  • elles sont définies avec let/let! au lieu de subject/subject!
  • ils ne sont pas ensemble l'anonyme subject ou de permettre à des attentes d'être appelée implicitement.

Quand les utiliser

C'est tout à fait légitime d'utiliser let afin de réduire les doubles emplois entre les exemples. Cependant, faites-le uniquement quand il n'est pas le sacrifice de test de la clarté. Le moment le plus sûr à utiliser let , c'est quand l' let de la variable objectif est tout à fait clair à partir de son nom (de sorte que le lecteur n'a pas à trouver la définition, qui pourrait être de plusieurs lignes, pour comprendre chaque exemple) et il est utilisé de la même manière dans chaque exemple. Si l'une de ces choses n'est pas vrai, envisager de définir l'objet dans un simple vieux variable locale ou l'appel d'une méthode de fabrique de la droite dans l'exemple.

let! est risqué, car il n'est pas paresseux. Si quelqu'un ajoute un exemple à l'exemple de groupe qui contient l' let!, mais l'exemple n'a pas besoin de l' let! variable,

  • cet exemple va être difficile à comprendre, parce que le lecteur va voir l' let! variable et se demander si et comment il affecte l'exemple
  • l'exemple sera plus lente qu'elle ne doit l'être, en raison du temps pris pour créer l' let! variablle

Donc, utiliser l' let!, si ce n'est dans les petites, simple exemple des groupes où il est moins probable que les futures exemple écrivains vont tomber dans ce piège.

La seule attente par exemple fétiche

Il y a une commune de la surexploitation des sujets ou let variables qui vaut la peine d'en discuter séparément. Certaines personnes aiment à l'utiliser comme ceci:

describe 'Calculator' do
  describe '#calculate' do
    subject { Calculator.calculate }
    it { is_expected.to be >= 0 }
    it { is_expected.to be <= 9 }
  end
end

(Ceci est un exemple simple d'une méthode qui retourne un nombre pour lequel nous avons besoin de deux attentes, mais ce style peut avoir beaucoup plus d'exemples/attentes si la méthode renvoie une plus compliqué valeur qui a besoin de beaucoup d'attentes et/ou a de nombreux effets secondaires qui ont besoin attentes.)

Les gens font cela parce qu'ils ont entendu dire que l'on devrait avoir une seule attente par exemple (ce qui est mélangé avec de la validité de la règle que l'on ne devrait tester une méthode d'appel par exemple) ou parce qu'ils sont dans l'amour avec RSpec trickiness. Ne pas le faire, que ce soit avec un anonyme ou le nom de l'objet ou un let variable! Ce style a plusieurs problèmes:

  • L'anonyme sujet n'est pas l'objet de la exemples de la méthode est l'objet. L'écriture du test de cette façon vis de la langue, ce qui rend plus difficile à penser.
  • Comme toujours, avec des exemples de ligne, il n'y a pas de place à expliquer le sens des attentes.
  • Le sujet doit être construit pour chaque exemple, qui est lent.

Au lieu de cela, écrire un seul exemple:

describe 'Calculator' do
  describe '#calculate' do
    it "returns a single-digit number" do
      result = Calculator.calculate
      expect(result).to be >= 0
      expect(result).to be <= 9
    end
  end
end

3voto

Ren Points 1136

Subject et let sont simplement des outils pour vous aider à nettoyer et accélérer votre tests. Les gens dans la rspec de la communauté ne les utiliser donc je ne vous inquiétez pas de savoir si c'est ok pour les utiliser ou pas. Ils peuvent être utilisés de la même manière, mais de servir des objectifs légèrement différents

Subject vous permet de déclarer un sujet de test, puis les réutiliser pour n'importe quel nombre de la suite de cas de test par la suite. Cela réduit la répétition de code (Séchage de votre code)

Let est une alternative à l' before: each blocs, qui assigne à des données de test pour les variables d'instance. Let vous donne quelques avantages. Tout d'abord, il met en cache la valeur sans l'affecter à une variable d'instance. Deuxièmement, il est paresseusement évalués, ce qui signifie qu'elle ne soit pas évalué jusqu'à une spécification de la demande. Ainsi, let vous aide à accélérer votre tests. Je pense aussi qu' let est plus facile à lire

1voto

nikkypx Points 1232

subject est ce qui est testé, généralement une instance ou une classe. let d'affecter des variables à vos tests, qui sont évaluées paresseusement par rapport à l'utilisation de variables d'instance. Il y a quelques bons exemples dans ce fil.

https://github.com/reachlocal/rspec-style-guide/issues/6

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