Argument
, BooleanOption
, OptionWithParameter
class Game
def initialize(name, genre)
@name = name
@genre = genre
end
def recommend
case genre
when :mmorpg then "Hey! Did you hear about #{name}? It's better than WoW!"
when :fps then "Yo! You must try this new shooter - #{name}!"
else "Have you tried #{name}? It's awesome!"
end
end
end
RSpec.describe Game do
it 'compares MMORPGs to WoW' do
game = Game.new('Guild Wars 2', :mmorpg)
expect(game.recommend).to eq 'Hey! Did you hear about Guild Wars 2? It\'s better than WoW!'
end
it 'calls FPS games shooters' do
game = Game.new('FarCry 4', :fps)
expect(game.recommend).to eq 'Yo! You must try this new shooter - FarCry 4!'
end
it 'calls games from unknown genres awesome' do
game = Game.new('The Witcher 3', :rpg)
expect(game.recommend).to eq 'Have you tried The Witcher 3? It\'s awesome!'
end
end
<това> прави <нещо>
, не <това> трябва да прави <нещо>
или тест, че <това> прави <нещо>
it 'calls it a shooter'
describe
описва какво тестваме
context
описва случай, който тестваме
describe
и context
ако имате повече от един тест в групаexpect
-а, дори да са еднакви
let
и before
за да премахнете повторения
expect(object).to be value #=> object.equal? value
expect(object).to eq value #=> object == value
expect(object).to be < value #=> object < value
expect(object).to be > value #=> object > value
expect(object).to match_array value #=> сравнява два масива, без да гледа реда на елементите
expect(object).to be_something #=> object.something?
expect(object).to have_something #=> object.has_something?
expect(object).to include(value) #=> object.include? value
expect { code }.to raise_error(Error, 'message')
to_not
.expect(object).to_not be value #=> object.equal? value
expect(object).to_not eq value #=> object == value
expect(object).to_not be < value #=> object < value
expect(object).to_not be > value #=> object > value
expect(object).to_not match_array value #=> сравнява два масива, без да гледа реда на елементите
expect(object).to_not be_something #=> object.something?
expect(object).to_not have_something #=> object.has_something?
expect(object).to_not include(value) #=> object.include? value
expect { code }.to_not raise_error
RSpec.describe '#launch_nukes' do
before { puts 'prepare nukes' }
after { puts 'destroy nukes' }
it 'can launch the nukes' do
puts 'launching nukes'
end
end
it 'does not have access to nukes' do
puts 'cannot launch nukes'
end
#=> prepare nukes
#=> launching nukes
#=> destroy nukes
#=> cannot launch nukes
before
, before(:each)
- изпълнява се преди всеки тест от групата
before(:all)
- изпълнява се веднъж преди всички тестове от групата
RSpec.describe '#launch_nukes' do
before do
@silo = NukeSilo.new
@silo.nukes = 10
end
it 'can launch the nukes' do
@silo.launch_at('Moon')
end
end
it 'does not have access to @silo' do
expect(@silo).to eq nil
end
let(:user) { User.new('Georgi', :admin) }
let(:game) { Game.new('The Witcher 3', :rpg) }
it 'can like a game' do
user.like(game)
expect(game.likes).to eq 1
expect(user.favourite_games).to match_array [game]
end
it 'can play a game' do
user.play(game, 2.hours)
expect(game.played_hours).to eq 2
expect(user.gameplay_hours).to eq 2
end
let(:user) { puts 'user initialized'; User.new('Georgi', :admin) }
it 'does something' do
expect(user.admin?).to be true
expect(user.admin?).to be true
expect(user.admin?).to be true
end
it 'does something else' do
expect(user.superadmin?).to be true
end
it 'does not test user' do
expect(true).to be true
end
#=> user initialized
#=> user initialized
let!(:user) { puts 'user initialized'; User.new('Georgi', :admin) }
it 'does something' do
expect(user.admin?).to be true
expect(user.admin?).to be true
expect(user.admin?).to be true
end
it 'does something else' do
expect(user.superadmin?).to be true
end
it 'does not test user' do
expect(true).to be true
end
#=> user initialized
#=> user initialized
#=> user initialized
let
създава обекта при първото му използване в тест
let!
създава обекта преди теста - независимо от това дали се използва
let
по подразбиране???
class Game
attr_accessor :likes
def initialize(name, genre)
# ...
@likes = 0
end
end
class User
def like(game)
game.likes += 1
end
end
it 'increases the like counter of the game' do
game = Game.new('The Witcher 3', :rpg)
user = User.new('Georgi', :admin)
user.like(game)
expect(game.likes).to eq 1
end
it 'increases the like counter of the game' do
game = double likes: 0
user = User.new('Georgi', :admin)
expect(game).to receive(:likes=).with(1)
user.like(game)
end
expect(...).to receive
фейлва теста, ако методът не бъде извиканclass Game
def popular?() likes >= 100 end
end
let(:game) { Game.new('The Witcher 3', :rpg) }
describe '#popular?' do
it 'returns true if the game is liked by at least 100 users' do
allow(game).to receive(:likes).and_return(123)
expect(game.popular?).to be true
end
end
allow(...).to receive
не фейлва теста, ако методът не бъде извиканclass NukeSilo
def launch_nukes_at(city)
# [CLASSIFIED]
"Nukes sent at #{city}"
end
end
class User
def launch_nukes(silo)
raise "No permissions" unless rank == :president
silo.launch_nukes_at '[CLASSIFIED]'
end
end
context 'when the user is a president' do
let(:silo) { NukeSilo.new }
it 'launches the nukes and reports what happened' do
user = User.new('Trump', :president)
expect(silo).to receive(:launch_nukes_at).and_return('World peace achieved')
expect(user.launch_nukes(silo)).to eq 'World peace achieved'
end
end
Game
, няма да се счупи теста
Game
, може да пропуснем да променим и User
Мокваме/стъбваме само ако...
Задайте ги сега!
В Ruby, код от други файлове се импортира с require
.
Например:
require 'bigdecimal'
require 'bigdecimal/util'
require 'foo'
търси файл foo.rb
в "пътя за зареждане"
require 'foo/bar'
търси директория foo
с файл bar.rb
.rb
отзад не е задължително да присъства
require './foo'
търси foo.rb
в текущата директория
require '/home/gangelov/foo.rb'
Всеки процес си има "текуща директория".
require './foo'
не винаги ще зареди това, което очаквате.$LOAD_PATH
$:
$:.unshift(path)
require './foo'
require_relative
require_relative 'foo'
зарежда 'foo' спрямо директорията на изпълняващия се файл
require './foo'
зарежда спрямо текущата директория на изпълняващия процесrequire
-а. Почти
main
обектът е същият
require
-и не правят нищо
require
може да зарежда .so
и .dll
файлове$LOAD_PATH
. ├── README.rdoc ├── Rakefile ├── bin │ └── skeptic ├── features ├── lib │ ├── skeptic │ │ ├── rules.rb │ │ └── scope.rb │ └── skeptic.rb ├── skeptic.gemspec └── spec
lib/
обикновено съдържа foo.rb
и lib/foo/
foo.rb
обикновено е единственото нещо в lib/
lib/foo
lib/
се добавя в load path
require 'foo'
или require 'foo/something'
require
областта
require
и $LOAD_PATH
и вижте какво се случва
load
е много сходен с require
, но има няколко разлики
load 'foo.rb'
load
-ове изпълняват файла
load
не може да зарежда .so
/.dll
библиотеки
load
има опционален параметър, с който може да обвие файла в анонимен модул