Add subject specs

This commit is contained in:
Michael Miller 2020-01-19 22:05:38 -07:00
parent e60c287216
commit 8381c08b05
5 changed files with 228 additions and 13 deletions

View file

@ -0,0 +1,140 @@
require "../../spec_helper"
# Examples taken from:
# https://relishapp.com/rspec/rspec-core/v/3-8/docs/subject/explicit-subject
# and modified to fit Spectator and Crystal.
Spectator.describe "Explicit Subject" do
context "A `subject` can be defined and used in the top level group scope" do
describe Array(Int32) do # TODO: Multiple arguments to describe/context.
subject { [1, 2, 3] }
it "has the prescribed elements" do
expect(subject).to eq([1, 2, 3])
end
end
end
context "The `subject` define in an outer group is available to inner groups" do
describe Array(Int32) do
subject { [1, 2, 3] }
describe "has some elements" do
it "which are the prescribed elements" do
expect(subject).to eq([1, 2, 3])
end
end
end
end
context "The `subject` is memoized within an example but not across examples" do
describe Array(Int32) do
# Changed to class variable to get around compiler error/crash.
# Unhandled exception: Negative argument (ArgumentError)
@@element_list = [1, 2, 3]
subject { @@element_list.pop }
# TODO: RSpec calls the "actual" block after the "change block".
xit "is memoized across calls (i.e. the block is invoked once)" do
expect do
3.times { subject }
end.to change { @@element_list }.from([1, 2, 3]).to([1, 2])
expect(subject).to eq(3)
end
# TODO: RSpec calls the "actual" block after the "change block".
xit "is not memoized across examples" do
expect { subject }.to change { @@element_list }.from([1, 2]).to([1])
expect(subject).to eq(2)
end
end
end
context "The `subject` is available in `before` blocks" do
describe Array(Int32) do # TODO: Multiple arguments to describe/context.
subject { [] of Int32 }
before_each { subject.push(1, 2, 3) }
it "has the prescribed elements" do
expect(subject).to eq([1, 2, 3])
end
end
end
context "Helper methods can be invoked from a `subject` definition block" do
describe Array(Int32) do # TODO: Multiple arguments to describe/context.
def prepared_array
[1, 2, 3]
end
subject { prepared_array }
it "has the prescribed elements" do
expect(subject).to eq([1, 2, 3])
end
end
end
context "Use the `subject!` bang method to call the definition block before the example" do
describe "eager loading with subject!" do
subject! { element_list.push(99) }
let(:element_list) { [1, 2, 3] }
it "calls the definition block before the example" do
element_list.push(5)
expect(element_list).to eq([1, 2, 3, 99, 5])
end
end
end
context "Use `subject(:name)` to define a memoized helper method" do
# Globals not supported, using class variable instead.
@@count = 0
describe "named subject" do
subject(:global_count) { @@count += 1 }
it "is memoized across calls (i.e. the block is invoked once)" do
expect do
2.times { global_count }
end.not_to change { global_count }.from(1)
end
it "is not cached across examples" do
expect(global_count).to eq(2)
end
it "is still available using the subject method" do
expect(subject).to eq(3)
end
it "works with the one-liner syntax" do
is_expected.to eq(4)
end
it "the subject and named helpers return the same object" do
expect(global_count).to eq(subject) # TODO: `be` matcher with value (no same? method).
end
it "is set to the block return value (i.e. the global $count)" do
expect(global_count).to eq(@@count) # TODO: `be` matcher with value (no same? method).
end
end
end
context "Use `subject!(:name)` to define a helper method called before the example" do
describe "eager loading using a named subject!" do
subject!(:updated_list) { element_list.push(99) }
let(:element_list) { [1, 2, 3] }
it "calls the definition block before the example" do
element_list.push(5)
expect(element_list).to eq([1, 2, 3, 99, 5])
expect(updated_list).to be(element_list)
end
end
end
end

View file

@ -0,0 +1,43 @@
require "../../spec_helper"
# Examples taken from:
# https://relishapp.com/rspec/rspec-core/v/3-8/docs/subject/implicitly-defined-subject
# and modified to fit Spectator and Crystal.
Spectator.describe "Implicitly defined subject" do
context "`subject` exposed in top-level group" do
describe Array(String) do
it "should be empty when first created" do
expect(subject).to be_empty
end
end
end
context "`subject` in a nested group" do
describe Array(String) do
describe "when first created" do
it "should be empty" do
expect(subject).to be_empty
end
end
end
end
context "`subject` in a nested group with a different class (innermost wins)" do
class ArrayWithOneElement < Array(String)
def initialize(*_args)
super
unshift "first element"
end
end
describe Array(String) do
describe ArrayWithOneElement do
context "referenced as subject" do
it "contains one element" do
expect(subject).to contain("first element")
end
end
end
end
end
end

View file

@ -0,0 +1,32 @@
require "../../spec_helper"
# Examples taken from:
# https://relishapp.com/rspec/rspec-core/v/3-8/docs/subject/one-liner-syntax
# and modified to fit Spectator and Crystal.
Spectator.describe "One-liner syntax" do
context "Implicit subject" do
describe Array(Int32) do
# Rather than:
# it "should be empty" do
# subject.should be_empty
# end
# TODO: Define `should` method on example to be `is_expected`.
# it { should be_empty }
# or
it { is_expected.to be_empty }
end
end
context "Explicit subject" do
describe Array(Int32) do
describe "with 3 items" do
subject { [1, 2, 3] }
# TODO: Define `should_not` method on example to be `is_expected.not_to`.
# it { should_not be_empty }
# or
it { is_expected.not_to be_empty }
end
end
end
end

View file

@ -1,13 +0,0 @@
require "../../spec_helper"
class Base; end
Spectator.describe "Subject" do
subject() { Base.new }
describe "#foo" do
it "bar" do
expect(subject).to be_a(Base)
end
end
end

13
spec/subject_spec.cr Normal file
View file

@ -0,0 +1,13 @@
require "./spec_helper"
class Base; end
Spectator.describe "Subject" do
subject { Base.new }
context "nested" do
it "inherits the parent explicit subject" do
expect(subject).to be_a(Base)
end
end
end