Anstelle des Standard-Rails-Minitests werden wir RSpec einführen, das eine höhere Akzeptanzrate aufweist als der Minitest in der Praxis. Wir werden mehr über ** TDD (Test Driven Development) und BDD (Behavior Driven Development) ** erfahren, die Testmethoden sind.
Capybara ・ ・ ・ Simuliert den Browserbetrieb von Webanwendungen FactoryBot gem ・ ・ Ein Juwel, das die Erstellung einer Testdatenbank unterstützt
group :development, :test do
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'rspec-rails', '~> 4.0.0'
gem 'factory_bot_rails', '~> 4.11'
gem 'capybara', '~> 2.13'
end
$bundle
$bin/rails g rspec:install
Minitest-Verzeichnis löschen
$rm -r ./test
Schreiben Sie die folgende Beschreibung in .rspec, damit das Ergebnis der Testausführung leicht sichtbar ist.
--format documentation
Färbung
--color
spec/spec_helper.rb
require 'capybara/rspec'
RSpec.configure do |config|
config.before(:each, type: :system) do
driven_by :selenium_chrome_headless
end
Installieren Sie Web-Treiber, mit denen Chrome Driver problemlos installiert werden kann
Gem'webdrivers'
hinzugefügt
$ mkdir spec/support
$ touch spec/support/driver_setting.rb
spec/support/driver_setting.rb
RSpec.configure do |config|
config.before(:each, type: :system) do
#Bei der Ausführung von Spec kann der Browser automatisch starten und das Verhalten überprüfen.
# driven_by(:selenium_chrome)
#Browser AUS, wenn Spec ausgeführt wird
driven_by(:selenium_chrome_headless)
end
end
Normalerweise können Sie eine Methode ohne FactoryBot nicht aufrufen user = FactoryBot.create(:user)
Durch Hinzufügen der obigen Einstellungen kann die Beschreibung von FactoryBot weggelassen werden. user = create(:user)
spec/rails_helper.rb
require "support/factory_bot"
spec/support/factory_bot.rb
RSpec.configure do |config|
#Vereinfachung des FactoryBot-Aufrufs
config.include FactoryBot::Syntax::Methods
#Verhindern Sie, dass das Werk aufgrund der Feder ordnungsgemäß geladen wird
config.before :all do
FactoryBot.reload
end
end
spec/rails_helper.rb
#Kommentieren Sie diesen Code aus
# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
** User Factory definieren **
spec/factories/users.rb
FactoryBot.define do
factory :user do
name { 'Benutzer testen' }
email { '[email protected]' }
password { 'password' }
end
end
** Definieren Sie eine Überprüfungsfabrik **
spec/factories/reviews.rb
FactoryBot.define do
factory :review do
title { "MyString" }
author { "MyString" }
description { "MyText" }
user
end
end
Dieses Juwel beschleunigt den Teststart
group :development do
gem 'spring-commands-rspec'
end
bundle install
und dann bundle exec spring binstub rspec
generieren eine rspec-Datei im bin-Verzeichnis
#!/usr/bin/env ruby
begin
load File.expand_path('../spring', __FILE__)
rescue LoadError => e
raise unless e.message.include?('spring')
end
require 'bundler/setup'
load Gem.bin_path('rspec-core', 'rspec')
Shoulda Mathers ist ein Juwel, mit dem Sie Tests präzise und intuitiv schreiben können, indem Sie RSpec und Minitest eine einzeilige Testsyntax hinzufügen.
group :test do
gem 'shoulda-matchers'
#Für Rails5 oder höher
gem 'shoulda-matchers', git: 'https://github.com/thoughtbot/shoulda-matchers.git', branch: 'rails-5'
end
spec/support/shoulda_matchers.rb
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
spec/rails_helper.rb
require "support/shoulda_matchers"
config/application.rb
require_relative 'boot'
require 'rails/all'
require 'uri'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module BookReviewApp
class Application < Rails::Application
config.load_defaults 5.1
config.generators.template_engine = :slim
config.i18n.default_locale = :ja
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]
config.generators do |g|
g.test_framework :rspec,
fixtures: false,
view_specs: false,
helper_specs: false,
routing_specs: false
end
end
end
Erstellen Sie einen Ordner mit dem Namen models im Ordner spec, erstellen Sie eine Datei user_spec.rb im Ordner models und schreiben Sie den folgenden Code
$ mkdir spec/models
$ touch spec/models/user_spec.rb
spec/mogels/user_spec.rb
require 'rails_helper'
RSpec.describe User, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
context "if name is entered" do
it 'if user registration is successful' do
end
end
context "if name is not entered" do
it 'if user registration fails' do
end
end
context 'if email is entered' do
it 'if user registration is successful' do
end
end
context 'if email is not entered' do
it 'if user registration fails' do
end
end
context "if password is entered" do
it 'if user registration is successful' do
end
end
context "if password is not entered" do
it 'if user registration fails' do
end
end
end
#Die Sprache der Testbeschreibung hängt von der Syntax ab
#Beispielsyntax
example 'japanisch' do
#Code schreiben
end
#es Syntax
it 'English' do
#Code schreiben
end
Wenn Sie nur diese Datei testen möchten, müssen Sie die Datei angeben
$ bundle exec rspec spec/models/user_spec.rb
Beispiele: Vorhandene Tests / Fehler: Fehlgeschlagene / ausstehende Tests: Nicht ausgeführte Tests
$ mkdir spec/system/
$ touch spec/system/reviews_spec.rb
spec/system/reviews_spec.rb
require 'rails_helper'
describe 'Überprüfen Sie die Verwaltungsfunktion', type: :system do
describe 'Listenanzeigefunktion' do
before do
#Benutzer A erstellen
#Erstellen Sie eine Bewertung, deren Autor Benutzer A ist
end
context 'Wenn der Benutzer angemeldet ist' do
before do
#Benutzer A meldet sich an
end
it 'Von Benutzer A erstellte Bewertungen werden angezeigt' do
#Stellen Sie sicher, dass der Titel der erstellten Überprüfung auf dem Bildschirm angezeigt wird
end
end
end
end
Beschreiben Sie in "beschreiben" "wofür Sie die Spezifikation beschreiben möchten" (Testziel). Die äußerste Beschreibung beschreibt das Thema der gesamten Spec-Datei. Beschreiben Sie ein detaillierteres Thema in der tieferen Beschreibung.
"Kontext" wird verwendet, um den Testinhalt nach der Variation von "Status / Status" zu klassifizieren. Sie können die Tests organisieren und vereinfachen, um festzustellen, ob sie unter verschiedenen Bedingungen ordnungsgemäß funktionieren müssen.
before
ist der Ort, an dem der Code geschrieben wird, um die" Voraussetzungen "des gesamten Bereichs auszuführen.
Wenn Sie zuvor in Beschreibung oder Kontext schreiben, wird der im Vorher-Block geschriebene Code ausgeführt, bevor der Testcode im entsprechenden Beschreibungs- oder Kontextbereich ausgeführt wird.
it
beschreibt das erwartete Verhalten in Sätzen und Code im Block. Wenn das Ziel wie erwartet funktioniert, ist der Test erfolgreich.
spec/system/reviews_spec.rb
require 'rails_helper'
describe 'Überprüfen Sie die Verwaltungsfunktion', type: :system do
describe 'Listenanzeigefunktion' do
before do
#Benutzer A erstellen
user_a = create(:user, name: 'Benutzer A.', email: '[email protected]')
#Erstellen Sie eine Bewertung, deren Autor Benutzer A ist
create(:review, name: 'Erste Überprüfung', user: user_a)
end
context 'Wenn der Benutzer angemeldet ist' do
before do
#Benutzer A meldet sich an
visit login_path
fill_in 'Mail Adresse', with: '[email protected]'
fill_in 'Passwort', with: 'password'
click_button 'Anmeldung'
end
it 'Von Benutzer A erstellte Bewertungen werden angezeigt' do
#Stellen Sie sicher, dass der Titel der erstellten Überprüfung auf dem Bildschirm angezeigt wird
expect(page).to have_content 'Erste Überprüfung'
end
end
end
end
#Wenn der Test fehlschlägt
$ bundle exec rspec spec/system/reviews_spec.rb
Überprüfen Sie die Verwaltungsfunktion
Listenanzeigefunktion
Wenn der Benutzer angemeldet ist
Von Benutzer A erstellte Bewertungen werden angezeigt(FAILED - 1)
Failures:
1)Überprüfungsverwaltungsfunktion Listenanzeigefunktion Von Benutzer A erstellte Überprüfungen werden angezeigt, wenn der Benutzer angemeldet ist.
Failure/Error: user_a = FactoryBot.create(user, name: 'Benutzer A.', email: '[email protected]')
NameError:
undefined local variable or method `user' for #<RSpec::ExampleGroups::Nested::Nested::Nested:0x00007fed26346f28>
[Screenshot]: tmp/screenshots/failures_r_spec_example_groups_nested_nested_nested_Vom Benutzer a erstellte Bewertungen werden angezeigt_412.png
# ./spec/system/reviews_spec.rb:7:in `block (3 levels) in <top (required)>'
Finished in 4.19 seconds (files took 5.32 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/system/reviews_spec.rb:21 #Überprüfungsverwaltungsfunktion Listenanzeigefunktion Von Benutzer A erstellte Überprüfungen werden angezeigt, wenn der Benutzer angemeldet ist.
spec/system/reviews_spec.rb
.
.
.
describe 'Neue Überprüfungsfunktion' do
let(:login_user) { :user_a }
before do
visit new_review_path
fill_in 'Titel', with: review_name
click_button 'Post'
end
context 'Bei der Eingabe eines Titels auf dem neuen Beitragsbildschirm' do
let(:review_name) { 'Schreiben Sie einen Test für einen neuen Beitrag' }
it 'Erfolgreich gepostet' do
expect(page).to have_selector 'alert-success', text: 'Schreiben Sie einen Test für einen neuen Beitrag'
end
end
context 'Wenn Sie den Titel nicht auf dem neuen Post-Bildschirm eingegeben haben' do
let(:review_name) { '' }
it 'Erhalten Sie einen Fehler' do
within '#error_explanation' do
expect(page).to have_content 'Bitte geben Sie einen Titel ein'
end
end
end
end
end
let ist eine Funktion, die in einem Bild verwendet werden kann, ähnlich wie "Zuweisen eines Werts zu einer Testbereichsvariablen vor der Verarbeitung" (es wird tatsächlich keine Variable erstellt).
let (Definitionsname) {Inhalt der Definition}
Mit einem Matcher namens have_selector können Sie bestimmte Elemente in HTML mit Selektoren (CSS-Selektoren) angeben.
have_selector
Mithilfe der darin aufgerufenen Methode können Sie den Suchbereich auf einen bestimmten Bereich auf dem Bildschirm eingrenzen, indem Sie den Inhalt der Seite innerhalb des Blocks "innerhalb" überprüfen.
innerhalb eines Bereichs angeben 'do
Machen Sie einen groben Umriss mit Kommentaren
spec/models/user_spec.rb
# validations
describe "validations" do
#Existenz
describe "presence" do
#Name, E-Mail-Adresse
it "name and email should not ro be empty/falsy"
#Passwort, Passwortbestätigung
context "when password and confirmation is not present" do
it "@user is invalid"
end
end
#Anzahl der Zeichen Zeichen
describe "charesters" do
#Name: bis zu 20 Zeichen
context "when name is too long"
it "@user is inavlid"
#Passwort, Passwortbestätigung: mindestens 6 Zeichen
describe "when password is too short"
it "@user is inavlid"
end
#E-Mail Format
describe "email format" do
#ungültiges Format
context "when invalid format" do
it "@user is inavlid"
#gültiges Format
context "when valid format" do
it "@user is valid"
end
end
end
end
Füllen Sie die Kommentare aus
spec/models/user_spec.rb
RSpec.describe User, type: :model do
#Ausstehende Vorlage
pending "add some examples to (or delete) #{__FILE__}"
# validations
describe "validations" do
#Existenz
describe "presence" do
#Name, E-Mail-Adresse
it { should validate_presence_of :name }
it { should validate_presence_of :email }
#Passwort, Passwortbestätigung
context "when password and confirmation is not present" do
before { user.password = user.password_confirmation = " " }
it { should_not be_valid }
end
end
#Anzahl der Zeichen Zeichen
describe "charesters" do
#Name: bis zu 20 Zeichen,Passwort: Mindestens 6 Zeichen
it { should validate_length_of(:name).is_at_most(20) }
it { should validate_length_of(:password).is_at_least(6) }
end
#E-Mail Format
describe "email format" do
#ungültiges Format
context "when invalid format" do
#Ungültiges Objekt
it "should be invalid" do
invalid_addr = %w[user@foo,com user_at_foo.org example.user@foo. foo@bar_baz.com foo@bar+baz.com]
invalid_addr.each do |addr|
user.email = addr
expect(user).not_to be_valid
end
end
end
end
#gültiges Format
context "when valid format" do
#Gültige Objekte
it "should be valid" do
valid_addr = %w[[email protected] [email protected] [email protected] [email protected]]
valid_addr.each do |addr|
user.email = addr
expect(user).to be_valid
end
end
end
end
end
↓ Testergebnis ↓
console.log
$ bundle exec rspec spec/models/user_spec.rb
User
add some examples to (or delete) /Users/kiyokawakouji/Rails-app/book_review_app/spec/models/user_spec.rb (PENDING: Not yet implemented)
validations
presence
is expected to validate that :name cannot be empty/falsy
is expected to validate that :email cannot be empty/falsy
when password and confirmation is not present
example at ./spec/models/user_spec.rb:17 (FAILED - 1)
charesters
is expected to validate that the length of :name is at most 20
is expected to validate that the length of :password is at least 6
email format
when invalid format
should be invalid (FAILED - 2)
when valid format
should be valid (FAILED - 3)
Pending: (Failures listed here are expected and do not affect your suite's status)
1) User add some examples to (or delete) /Users/kiyokawakouji/Rails-app/book_review_app/spec/models/user_spec.rb
# Not yet implemented
# ./spec/models/user_spec.rb:5
Failures:
1) User validations presence when password and confirmation is not present
Failure/Error: before { user.password = user.password_confirmation = " " }
NameError:
undefined local variable or method `user' for #<RSpec::ExampleGroups::User::Validations::Presence::WhenPasswordAndConfirmationIsNotPresent:0x00007fd1586e2770>
# ./spec/models/user_spec.rb:16:in `block (5 levels) in <top (required)>'
2) User validations email format when invalid format should be invalid
Failure/Error: user.email = addr
NameError:
undefined local variable or method `user' for #<RSpec::ExampleGroups::User::Validations::EmailFormat::WhenInvalidFormat:0x00007fd15831d6f8>
# ./spec/models/user_spec.rb:34:in `block (6 levels) in <top (required)>'
# ./spec/models/user_spec.rb:33:in `each'
# ./spec/models/user_spec.rb:33:in `block (5 levels) in <top (required)>'
3) User validations when valid format should be valid
Failure/Error: user.email = addr
NameError:
undefined local variable or method `user' for #<RSpec::ExampleGroups::User::Validations::WhenValidFormat:0x00007fd1582d5790>
# ./spec/models/user_spec.rb:46:in `block (5 levels) in <top (required)>'
# ./spec/models/user_spec.rb:45:in `each'
# ./spec/models/user_spec.rb:45:in `block (4 levels) in <top (required)>'
Finished in 0.61427 seconds (files took 5.94 seconds to load)
8 examples, 3 failures, 1 pending
Failed examples:
rspec ./spec/models/user_spec.rb:17 # User validations presence when password and confirmation is not present
rspec ./spec/models/user_spec.rb:31 # User validations email format when invalid format should be invalid
rspec ./spec/models/user_spec.rb:43 # User validations when valid format should be valid
** Erklärung der Testergebnisse unten **
Wie im Kommentar geschrieben, ist "panding" eine Vorlage, die zeigt, wie man RSpec schreibt (diesmal habe ich es gewagt, es aufzuwecken, ohne es zu löschen), also ist es vorbei.
(FAILED-number)
zeigt an, dass der Testcode fehlgeschlagen ist. Diesmal ist der Testcode an drei Stellen fehlgeschlagen.
Failures: ~
gibt den entsprechenden Code und die Fehlerdetails aus, bei denen der Test fehlgeschlagen ist.
Fehlerbeispiel: ~
gibt die Zeile des entsprechenden Codes in der Datei aus, in der der Test fehlgeschlagen ist, und das erwartete Verhalten.
Da dies ein Modelltest ist, werden wir die Validierungen überprüfen
app/models/user.rb
class User < ApplicationRecord
devise :database_authenticatable, :rememberable,
:validatable, :timeoutable, :registerable, :confirmable
#Ist der Wert des Namens leer?
validates :name, presence: true
#Ist der Wert des Namens 20 Zeichen oder weniger?
validates :name, length: { maximum: 20 }
#Verringern Sie die E-Mail-Adresse, wenn Sie die E-Mail-Adresse in der Datenbank speichern
before_save { self.email = email.downcase }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
#Entspricht die E-Mail der Bestätigungseingabe?
validates :email, { presence: true, format: { with: VALID_EMAIL_REGEX } }
validates :email, :encrypted_password, confirmation: true
#Ist der Passwortwert leer?
validates :password, presence: true
#Ist das Passwort 6 Zeichen oder mehr?
validates :password, length: { minimum: 6 }
#Benutzer verknüpfen und in der Datenbank überprüfen
has_many :reviews, dependent: :destroy, foreign_key: :review_user_id
end
** Einstellung, um nur fehlgeschlagene Tests erneut auszuführen (Option --only-failed) **
spec_helper.rb
RSpec.configure do |config|
config.example_status_persistence_file_path = "./spec/examples.txt"
end
------------------------------------------------------------------
Wenn Sie Git verwenden.Fügen Sie gitignore auch die folgenden Einstellungen hinzu.
spec/examples.txt
$ bundle exec rspec --only-failures
Liste der Optionen für rspec
$ rspec --help
Ausgabe ohne Ausführung einer Testliste
$ rspec --dry-run
Ausgangstestwarnung
$ rspec --warnings
Dieser Befehl zeigt eine Warnung in der Spezifikationsdatei an. Wenn ein Rechtschreibfehler vorliegt, geben Sie ihn in die Warnung ein und geben Sie ihn aus
Als ich $ rsoec --warnings
ausprobierte, wurde die folgende Ausgabe ausgegeben
WARN: Unresolved or ambiguous specs during Gem::Specification.reset:
diff-lcs (>= 1.2.0, < 2.0)
Available/installed versions of this gem:
- 1.4
- 1.3
WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'
Please report a bug if this causes problems.
~~Kürzung~~
Es wird gesagt, dass dasselbe Juwel in mehreren Versionen installiert ist und es nicht möglich ist, zu entscheiden, welches auf dem System behandelt werden soll. Sie müssen die alte Version des Edelsteins entfernen und auf eine eingrenzen oder sich für eine bestimmte Version entscheiden.
** Gesamttest ** ・ Systemspezifikation / Funktionsspezifikation ・ Integrationstest (Anforderungsspezifikation) ・ Funktionsprüfung (Controller Spec) ** Einzelteiletest ** ・ Modell (Modellspezifikation) ・ Routing-Spezifikation · View Spec ・ Helferspez ・ Mailer (Mailer-Spezifikation) ・ Job (Jobspezifikation)
Sie müssen sicherstellen, dass der Testcode wie vorgesehen funktioniert. Dies wird auch als "Ausüben des zu testenden Codes" bezeichnet. Um zu beweisen, dass es sich nicht um ein falsches Positiv handelt, ändern Sie beispielsweise "to" in "to_not" und kehren Sie die Erwartung um.
spec/models/user_spec.rb
#Wenn kein Name vorhanden ist, befindet er sich in einem ungültigen Zustand(Erfolg)
it "is invalid without a first name" do
user = User.new(first_name: nil)
user.valid?
expect(user.errors[:first_name]).to include("can't be blank")
end
#Wenn kein Name vorhanden ist, befindet er sich in einem ungültigen Zustand(Fehler)
it "is invalid without a first name" do
user = User.new(first_name: nil)
user.valid?
expect(user.errors[:first_name]).to_not include("can't be blank")
end
Grundlagen der Rails-RSpec-Vorbereitung und des Testcodes [Rails] Einführung "RSpec + FactoryBot + Capybara + Webdrivers" und erste Einstellung zum Testen des Schreibens Erstellen einer SystemSpec-Umgebung mit Rails + Selenium + Docker https://github.com/everydayrails/everydayrails-rspec-2017 Einführung in RSpec, das verwendet werden kann, Teil 1 "Grundlegende Syntax und nützliche Funktionen von RSpec" RSpec-Einstellungen Nützliche Optionen für Rspec Verwendung von Rails-Rückrufen, die ich nach dem Leiden endlich verstanden habe
Recommended Posts