Es ist ein Memorandum.
Verweise Everyday Rails-Einführung in das Testen von Schienen mit RSpec https://leanpub.com/everydayrailsrspec-jp
Dies ist eine Methode zur Beseitigung von Codeduplizierungen und zur Standardisierung der Verarbeitung (Anmeldeverarbeitung usw.). Wenn beispielsweise fünf Tests den Anmeldevorgang im Voraus ausführen und die Anmeldeschaltfläche geändert wird, sind fünf Änderungen erforderlich. Die Aufteilung in ein einzelnes Modul verbessert die Lesbarkeit und reduziert Änderungen auf ein Minimum.
Versuchen Sie, den folgenden Anmeldevorgang in Module aufzuteilen
#Anmeldebildschirm abrufen
visit root_path
#Klicken Sie auf Anmelden
click_link "Sign in"
#Geben Sie die E-Mail-Adresse des Benutzers in das Textfeld E-Mail ein
fill_in "Email", with: user.email
#Geben Sie das Passwort wie oben ein
fill_in "Password", with: user.password
#Klicken Sie auf die Schaltfläche Anmelden
click_button "Log in"
Angenommen, der Code in den in diesem Modul beschriebenen Methoden ist über den gesamten Test verteilt.
Um diesen Code zu trennen, erstellen Sie spec / suprot / login_support.rb und modularisieren Sie ihn.
login_support.rb
module LoginSupport
def sign_in_as(user)
visit root_path
click_link "Sign in"
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Log in"
end
#Lesen Sie die gesamte RSpec
RSpec.configure do |config|
config.include LoginSupport
end
↓
#Wenn Sie es für jeden Test explizit lesen möchten, in der Spezifikationsdatei, die Sie lesen möchten
include LoginSupport
#Wenn ja, wird es gelesen.
Jetzt können Sie die Methoden (Hilfsmethoden) im Modul aufrufen. Vergleichen wir vor und nach dem Umschreiben. Everyday Rails - Leihen Sie sich den Code aus, um mit dem Testen von Rails mit RSpec zu beginnen.
Vor dem Austausch
projects_spec.rb
require 'rails_helper'
RSpec.feature "Projects", type: :feature do
scenario "user creates a new project" do
user = FactoryBot.create(:user)
#von hier
visit root_path
click_link "Sign in"
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Log in"
#Ersetzen Sie bis hierher durch die Hilfsmethode
expect {
click_link "New Project"
fill_in "Name", with: "Test Project"
fill_in "Description", with: "Trying out Capybara"
click_button "Create Project"
expect(page).to have_content "Project was successfully created"
expect(page).to have_content "Test Project"
expect(page).to have_content "Owner: #{user.name}"
}.to change(user.projects, :count).by(1)
end
end
Nach dem Austausch
projects_spec.rb
require 'rails_helper'
RSpec.feature "Projects", type: :feature do
scenario "user creates a new project" do
user = FactoryBot.create(:user)
#von hier
sign_in_as(user)
#Oder
sign_in_as user
#Aber ok
#Ich habe das Obige durch eine Hilfsmethode ersetzt
expect {
click_link "New Project"
fill_in "Name", with: "Test Project"
fill_in "Description", with: "Trying out Capybara"
click_button "Create Project"
expect(page).to have_content "Project was successfully created"
expect(page).to have_content "Test Project"
expect(page).to have_content "Owner: #{user.name}"
}.to change(user.projects, :count).by(1)
end
end
Das Wichtigste dabei ist, den Methodennamen leicht verständlich zu machen. Es ist wichtig, einen Namen im Auge zu behalten, den Sie leicht verstehen können, da Sie den Vorgang nicht unter dem Namen der Methode verstehen können. Wenn Sie auf die Originaldatei verweisen, wird der Test nur unpraktisch.
In einigen Fällen werden die für den Test erforderlichen Daten vor dem Test eingerichtet (Datenerstellungsprozess, z. B. Benutzererstellung), bevor Beschreibung oder Kontext ausgeführt werden. Da before jedes Mal ausgeführt wird, wenn eine Beschreibung oder ein Kontext ausgeführt wird, können die folgenden Probleme auftreten.
Es ist das verzögerte Lesen durch let, das dies klärt. Da let nur ausgeführt wird, wenn es aufgerufen wird, können die oben genannten Probleme gelöst werden. Vergleichen wir vor und nach dem Umschreiben. Everyday Rails - Leihen Sie sich den Code aus, um mit dem Testen von Rails mit RSpec zu beginnen.
unbenutzt lassen
note_spec.rb
require 'rails_helper'
RSpec.describe Note, type: :model do
before do
#Benutzer erstellt
@user = User.create(
first_name: "Joe",
last_name: "Tester",
email: "[email protected]",
password: "dottle-nouveau-pavilion-tights-furze",
)
#Projekterstellung
@project = @user.projects.create(
name: "Test Project",
)
end
it "Muss gültig sein, wenn Benutzer, Projekte, Nachrichten vorhanden sind" do
note = Note.new(
message: "This is a sample note.",
user: @user,
project: @project,
)
expect(note).to be_valid
end
it "Wenn keine Nachricht vorhanden ist, befindet sie sich in einem ungültigen Zustand" do
note = Note.new(message: nil)
note.valid?
expect(note.errors[:message]).to include("can't be blank")
end
describe "Suchen Sie nach Nachrichten, die der Zeichenfolge entsprechen" do
before do
@note1 = @project.notes.create(
message: "This is the first note.",
user: @user,
)
@note2 = @project.notes.create(
message: "This is the second note.",
user: @user,
)
@note3 = @project.notes.create(
message: "First, preheat the oven.",
user: @user,
)
end
context "Bei der Suche nach passenden Daten" do
it "Rückgabe von Notizen, die mit der Suchzeichenfolge übereinstimmen" do
expect(Note.search("first")).to include(@note1, @note3)
end
end
context "Wenn keine übereinstimmenden Daten gefunden werden" do
it "Rückgabe einer leeren Sammlung" do
expect(Note.search("message")).to be_empty
end
end
end
end
benutze let
note_spec.rb
require 'rails_helper'
RSpec.describe Note, type: :model do
#benutze let statt vorher
let(:user) { FactoryBot.create(:user) }
let(:project) { FactoryBot.create(:project, owner: user) }
it "Muss gültig sein, wenn Benutzer, Projekte, Nachrichten vorhanden sind" do
note = Note.new(
message: "This is a sample note.",
user: user,
project: project,
)
expect(note).to be_valid
end
it "Wenn keine Nachricht vorhanden ist, befindet sie sich in einem ungültigen Zustand" do
note = Note.new(message: nil)
note.valid?
expect(note.errors[:message]).to include("can't be blank")
end
describe "Suchen Sie nach Nachrichten, die der Zeichenfolge entsprechen" do
#benutze let statt vorher
let(:note1) {
FactoryBot.create(:note,
project: project,
user: user,
message: "This is the first note."
)
}
let(:note2) {
FactoryBot.create(:note,
project: project,
user: user,
message: "This is the second note."
)
}
let(:note3) {
FactoryBot.create(:note,
project: project,
user: user,
message: "First, preheat the oven."
)
}
context "Bei der Suche nach passenden Daten" do
it "Rückgabe von Notizen, die mit der Suchzeichenfolge übereinstimmen" do
expect(Note.search("first")).to include(note1, note3)
end
end
context "Wenn keine übereinstimmenden Daten gefunden werden" do
it "Rückgabe einer leeren Sammlung" do
expect(Note.search("message")).to be_empty
end
end
end
end
Bei der vorherigen Verwendung wurden Instanzvariablen verwendet, um den Bereich im Test zu überschreiten. In let wird dies jedoch durch Variablen beschrieben. Nachdem der Test bestanden wurde, tritt hier ein Problem auf. Fügen Sie Expect (Note.count) .zu Gleichung 3 zum letzten "Zurückgeben einer leeren Sammlung" hinzu.
note_spec.rb
context "Wenn keine übereinstimmenden Daten gefunden werden" do
it "Rückgabe einer leeren Sammlung" do
expect(Note.search("message")).to be_empty
#Fügen Sie diesen Satz hinzu
expect(Note.count).to eq 3
end
end
end
end
Die obige Beschreibung besteht den Test nicht. Der Grund ist einfach: Lassen Sie uns faul lesen.
Kurz gesagt, es werden keine Daten erstellt, wenn sie nicht aufgerufen werden.
Mit Expect (Note.count) .zu Gleichung 3 geht der Test zur DB, um die Daten zu finden. Natürlich ist die DB leer, weil let nicht aufgerufen wird. Da die Definition der Erwartung jedoch lautet, dass die Anzahl der Daten in der Notiz gleich 3 ist, die Anzahl der Daten 0 ist, der Test nicht bestanden wird und ein Fehler auftritt.
Eine Möglichkeit, dies zu lösen, besteht darin, einfach let aufzurufen. Ein Beispiel mit let! Wird unten gezeigt.
note_spec.rb
#lassen statt lassen!verwenden
let!(:note1) {
FactoryBot.create(:note,
project: project,
user: user,
message: "This is the first note."
)
}
let!(:note2) {
FactoryBot.create(:note,
project: project,
user: user,
message: "This is the second note."
)
}
let!(:note3) {
FactoryBot.create(:note,
project: project,
user: user,
message: "First, preheat the oven."
)
}
#====Kürzung=====
context "Wenn keine übereinstimmenden Daten gefunden werden" do
it "Rückgabe einer leeren Sammlung" do
expect(Note.search("message")).to be_empty
#Fügen Sie diesen Satz hinzu
expect(Note.count).to eq 3
end
end
end
end
Dies wird den Test bestehen. Lassen Sie! Preloads, während let delay liest. Das Bild ist das gleiche wie zuvor, und für jeden Bewertungsblock werden Daten erstellt.
Dies bedeutet, dass die oben genannten Probleme nicht behoben wurden. In diesem Fall hängt es von der Situation ab, ob Sie es vorher verwenden oder lassen! Aus der Sicht meines Lernens habe ich das Gefühl, dass es in Ordnung ist, vorher zu verwenden und richtig zu lassen.
Als Ergebnis im Grunde lassen! Ich möchte in die Richtung gehen, nicht zu benutzen. Ich würde es gerne vorher belassen, wenn ein Vorladen erforderlich ist, anstatt Fehlinterpretationen oder Pocha-Fehler zu machen, da es nur einen subtilen Unterschied zwischen let und let gibt!
Mit shared_context können Sie das erforderliche Setup mit mehreren Testdateien durchführen. Die Verwendung ähnelt dem Support-Modul. Vergleichen wir vor und nach dem Umschreiben. Everyday Rails - Leihen Sie sich den Code aus, um mit dem Testen von Rails mit RSpec zu beginnen.
tasks_controller.rb
require 'rails_helper'
RSpec.describe TasksController, type: :controller do
#Fassen Sie das Setup hier zusammen
let(:user) { FactoryBot.create(:user) }
let(:project) { FactoryBot.create(:project, owner: user) }
let(:task) { project.tasks.create!(name: "Task task") }
describe "#show" do
it "responds with JSON formatted output" do
sign_in user
get :show, format: :json,
params: { project_id: project.id, id: task.id }
expect(response.content_type).to eq "application/json"
end
end
describe "#create" do
it "responds with JSON formatted output" do
new_task = { name: "New test task" }
sign_in user
post :create, format: :json,
params: { project_id: project.id, task: new_task }
expect(response.content_type).to eq "application/json"
end
it "adds a new task to the project" do
new_task = { name: "New test task" }
sign_in user
expect {
post :create, format: :json,
params: { project_id: project.id, task: new_task }
}.to change(project.tasks, :count).by(1)
end
it "requires authentication" do
new_task = { name: "New test task" }
# Don't sign in this time ...
expect {
post :create, format: :json,
params: { project_id: project.id, task: new_task }
}.to_not change(project.tasks, :count)
expect(response).to_not be_success
end
end
end
Erstellen Sie eine separate Datei und kombinieren Sie die 3 Zeilen von let mit shared_context Erstellen Sie spec / support / context / project_setup.rb
project_setup.rb
RSpec.shared_context "project setup" do
let(:user) { FactoryBot.create(:user) }
let(:project) { FactoryBot.create(:project, owner: user) }
let(:task) { project.tasks.create!(name: "Task task") }
end
Gehen Sie zurück zu task_controller.rb und schreiben Sie den let-Teil neu.
tasks_controller.rb
require 'rails_helper'
RSpec.describe TasksController, type: :controller do
#Löschen lassen und projizieren_setup.Include rb.
include_context "project setup"
#====Unten weggelassen=====
Jetzt haben Sie mehrere Testdateien, um die erforderlichen Setups in einer zu kombinieren.
・ Support-Modul Sie können gängige Verarbeitungen wie Hilfsmethoden in einer separaten Datei ausschneiden und bei Bedarf einfügen. · Lassen Es ist möglich, Daten zu erstellen, die zum Testen verwendet werden sollen. Auswirkungen auf die Prüfung durch verzögertes Laden Es ist zu erwarten, dass sich die Leistung verbessert. ・ Shared_context Es ist möglich, das zum Testen verwendete Setup zusammenzustellen. Schneiden Sie es in eine andere Datei aus und verwenden Sie es als Include.
Vielen Dank, dass Sie bis zum Ende bei uns bleiben. Wenn Sie Anregungen oder Ratschläge haben, würde ich mich freuen, wenn Sie einen Kommentar abgeben könnten.
Recommended Posts