Короткий зміст: Тема RSpec - це спеціальна змінна, яка відноситься до об'єкта, що тестується. На нього можна покласти сподівання неявно, що підтримує однорядкові приклади. Це зрозуміло для читача в деяких ідіоматичних випадках, але в іншому випадку важко зрозуміти, і його слід уникати. let
Змінні RSpec - це просто ліниво створені (запам'ятовувані) змінні. Вони не такі важкі для вивчення, як предмет, але все одно можуть призвести до заплутаних тестів, тому їх слід використовувати з розсудом.
Тема
Як це працює
Суб'єкт - це об'єкт, що перевіряється. RSpec має чітке уявлення про предмет. Це може бути визначено або не визначено. Якщо це так, RSpec може викликати на ньому методи, не посилаючись на нього явно.
За замовчуванням, якщо першим аргументом найвіддаленішої групи прикладів ( describe
або context
блоків) є клас, RSpec створює екземпляр цього класу і призначає його темі. Наприклад, такі пропуски:
class A
end
describe A do
it "is instantiated by RSpec" do
expect(subject).to be_an(A)
end
end
Ви можете визначити предмет самостійно за допомогою subject
:
describe "anonymous subject" do
subject { A.new }
it "has been instantiated" do
expect(subject).to be_an(A)
end
end
Ви можете дати темі ім’я, коли його визначаєте:
describe "named subject" do
subject(:a) { A.new }
it "has been instantiated" do
expect(a).to be_an(A)
end
end
Навіть якщо ви називаєте тему, ви все одно можете посилатися на неї анонімно:
describe "named subject" do
subject(:a) { A.new }
it "has been instantiated" do
expect(subject).to be_an(A)
end
end
Ви можете визначити більше одного іменованого предмета. Останній визначений названий суб’єкт - анонімний subject
.
Однак тема визначена,
Це ліниво. Тобто, неявна інстанція описуваного класу або виконання блоку, якому передано subject
, не відбувається, поки subject
або не буде вказано названий предмет у прикладі. Якщо ви хочете, щоб ваш експлікт-предмет був інтенсивно створений (до запуску прикладу в його групі), скажіть subject!
замість subject
.
На нього можна неявно покласти сподівання (без написання subject
або імені названого суб’єкта):
describe A do
it { is_expected.to be_an(A) }
end
Тема існує для підтримки цього однорядкового синтаксису.
Коли його використовувати
Імпліцитний subject
(що випливає з групи прикладів) важко зрозуміти, оскільки
- Це зроблено за кулісами.
- Незалежно від того, використовується воно неявно (за допомогою виклику
is_expected
без явного приймача) або явно (як subject
), воно не дає читачеві ніякої інформації про роль або природу об’єкта, на який викликається очікування.
- Приклад синтаксису з одним вкладишем не має прикладу опису (аргумент рядка для
it
звичайного синтаксису прикладу), тому єдиною інформацією, яку читач має про мету прикладу, є саме очікування.
Тому корисно використовувати неявну тему лише тоді, коли контекст, ймовірно, добре розуміється всіма читачами, і насправді немає потреби в прикладі опису . Канонічний випадок - це тестування перевірок ActiveRecord за допомогою збігів, що відповідають за вимоги:
describe Article do
it { is_expected.to validate_presence_of(:title) }
end
Експлікт анонімний subject
(визначений subject
без імені) трохи кращий, тому що читач може бачити, як він створений, але
- він все ще може розмістити екземпляр теми далеко від місця, де він використовується (наприклад, у верхній частині групи прикладів з багатьма прикладами, які його використовують), чого важко дотримуватися, і
- у нього є інші проблеми, які робить неявний суб’єкт.
Іменований предмет надає ім’я, що виявляє намір, але єдина причина використовувати названий предмет замість let
змінної - це те, що ви хочете використовувати анонімний предмет час від часу, і ми просто пояснили, чому анонімний суб’єкт важко зрозуміти.
Отже, законне використання явного анонімного subject
або названого суб’єкта дуже рідкісне .
let
змінні
Як вони працюють
let
змінні так само, як названі предмети, за винятком двох відмінностей:
- вони визначаються за допомогою
let
/ let!
замість subject
/subject!
- вони не встановлюють анонімних
subject
чи не дозволяють неявно викликати до нього сподівання.
Коли їх використовувати
Це цілком законно використовувати let
для зменшення дублювання серед прикладів. Однак робіть це лише тоді, коли це не жертвує ясністю тесту. Найбезпечніший час використання let
- це коли let
змінна повністю зрозуміла з її назви (щоб читачеві не потрібно було знаходити визначення, яке може бути на відстані рядків, щоб зрозуміти кожен приклад), і воно використовується так само у кожному прикладі. Якщо будь-яка з цих речей не відповідає дійсності, спробуйте визначити об’єкт у звичайній старій локальній змінній або викликати заводський метод прямо в прикладі.
let!
ризиковано, бо це не лінь. Якщо хтось додає приклад до групи прикладів, що містить let!
, але приклад не потребує let!
змінної,
- цей приклад буде важко зрозуміти, оскільки читач побачить
let!
змінну і запитає, чи впливає і як це впливає на приклад
- приклад буде повільнішим, ніж потрібно, через час,
let!
затрачений на створення змінної
Тож використовуйте let!
, якщо взагалі, лише невеликі, прості групи прикладів, де менш імовірно, що майбутні автори прикладів потраплять у цю пастку.
Фетиш з одним очікуванням на приклад
Існує загальне надмірне використання предметів або let
змінних, які варто обговорити окремо. Деякі люди люблять використовувати їх так:
describe 'Calculator' do
describe '#calculate' do
subject { Calculator.calculate }
it { is_expected.to be >= 0 }
it { is_expected.to be <= 9 }
end
end
(Це простий приклад методу, який повертає число, для якого нам потрібні два очікування, але цей стиль може мати набагато більше прикладів / очікувань, якщо метод повертає більш складне значення, яке потребує багатьох очікувань та / або має багато побічних ефектів, які всім потрібні очікування.)
Люди роблять це тому, що чули, що на приклад потрібно мати лише одне очікування (яке змішується з діючим правилом, згідно з яким потрібно протестувати лише один виклик методу на приклад), або тому, що вони закохані в хитрість RSpec. Не робіть цього, будь то анонімний або названий предмет чи let
змінна! Цей стиль має кілька проблем:
- Анонімний суб’єкт не є предметом прикладів - метод є предметом. Написання тесту таким чином псує мову, ускладнюючи роздуми.
- Як завжди з однорядковими прикладами, немає місця для пояснення значення очікувань.
- Тема повинна бути побудована для кожного прикладу, що є повільним.
Натомість напишіть один приклад:
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