This is part 2 of a planned 3 part series
Introduction:
In part 1, this was achieved;
- Initialising project
- Writing a test for when nothing has been scanned
In part 2, this is going to be handled;
- Scanning of A
- Scanning of B
- Scanning of C
- Scanning of D
Tests will be run using;
⎵ + t
: run entire test (⎵
means the keyboardspace bar button
)⎵ + l
: run last test⎵ + s
: run nearest test
Scanning of A:
Add another context to check for when A
has been scanned. The file changes to this;
class CheckOut
def initialize(pricing_rules)
end
def total
0
end
end
RSpec.describe 'checkout' do
context 'when nothing has been scanned' do
it 'shows a total of zero' do
pricing_rules = :Rule
checkout = CheckOut.new(pricing_rules)
total = checkout.total
expect(total).to eq 0
end
end
context 'when A has been scanned' do
it 'shows the price of A' do
expect(total).to eq 50
end
end
end
Run the test by pressing ⎵ + t
. We get this error;
~
./bin/rspec spec/check_out_spec.rb
Randomized with seed 34364
.F
Failures:
1) checkout when A has been scanned shows the price of A
Failure/Error: expect(total).to eq 50
NameError:
undefined local variable or method `total' for #<RSpec::ExampleGroups::Checkout::WhenAHasBeenScanned "shows the price of A" (./spec/check_out_spec.rb:22)>
# ./spec/check_out_spec.rb:24:in `block (3 levels) in <top (required)>'
Finished in 0.00256 seconds (files took 0.05539 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/check_out_spec.rb:22 # checkout when A has been scanned shows the price of A
Randomized with seed 34364
shell returned 1
Press ENTER or type command to continue
Modify the file to add the lines specifying what total
is and define pricing_rules
;
class CheckOut
def initialize(pricing_rules)
end
def total
0
end
end
RSpec.describe 'checkout' do
context 'when nothing has been scanned' do
it 'shows a total of zero' do
pricing_rules = :Rule
checkout = CheckOut.new(pricing_rules)
total = checkout.total
expect(total).to eq 0
end
end
context 'when A has been scanned' do
it 'shows the price of A' do
pricing_rules = :Rule
checkout = CheckOut.new(pricing_rules)
total = checkout.total
expect(total).to eq 50
end
end
end
When the test is run, as expected we get the error as shown below;
./bin/rspec spec/check_out_spec.rb
Randomized with seed 5579
.F
Failures:
1) checkout when A has been scanned shows the price of A
Failure/Error: expect(total).to eq 50
expected: 50
got: 0
(compared using ==)
# ./spec/check_out_spec.rb:27:in `block (3 levels) in <top (required)>'
Finished in 0.00758 seconds (files took 0.0523 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/check_out_spec.rb:22 # checkout when A has been scanned shows the price of A
Randomized with seed 5579
shell returned 1
Press ENTER or type command to continue
A change needs to be made to the spec to include scanning of Item A. This changes the file to be;
class CheckOut
def initialize(pricing_rules)
end
def total
0
end
end
RSpec.describe 'checkout' do
context 'when nothing has been scanned' do
it 'shows a total of zero' do
pricing_rules = :Rule
checkout = CheckOut.new(pricing_rules)
total = checkout.total
expect(total).to eq 0
end
end
context 'when A has been scanned' do
it 'shows the price of A' do
pricing_rules = :Rule
checkout = CheckOut.new(pricing_rules)
checkout.scan('A')
total = checkout.total
expect(total).to eq 50
end
end
end
When checkout.scan('A')
is added, we get this error;
./bin/rspec spec/check_out_spec.rb
Randomized with seed 45438
.F
Failures:
1) checkout when A has been scanned shows the price of A
Failure/Error: checkout.scan('A')
NoMethodError:
undefined method `scan' for #<CheckOut:0x0000000130ca8448>
# ./spec/check_out_spec.rb:26:in `block (3 levels) in <top (required)>'
Finished in 0.00187 seconds (files took 0.04966 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/check_out_spec.rb:22 # checkout when A has been scanned shows the price of A
Randomized with seed 45438
shell returned 1
Press ENTER or type command to continue
Add the method: scan(item)
to CheckOut
class to fix this error;
class CheckOut
def initialize(pricing_rules)
end
def total
0
end
def scan(item)
end
end
Now we are back to the previous error when the test is run;
./bin/rspec spec/check_out_spec.rb
Randomized with seed 56370
.F
Failures:
1) checkout when A has been scanned shows the price of A
Failure/Error: expect(total).to eq 50
expected: 50
got: 0
(compared using ==)
# ./spec/check_out_spec.rb:33:in `block (3 levels) in <top (required)>'
Finished in 0.00768 seconds (files took 0.04974 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/check_out_spec.rb:26 # checkout when A has been scanned shows the price of A
Randomized with seed 56370
shell returned 1
Press ENTER or type command to continue
To fix this error, we make three changes to the CheckOut
class as below;
class CheckOut
def initialize(pricing_rules)
@total = 0
end
def total
@total
end
def scan(item)
@total = 50
end
end
Now when the test is run, all the current two tests will pass successfully;
./bin/rspec spec/check_out_spec.rb
Randomized with seed 4857
..
Finished in 0.00201 seconds (files took 0.04948 seconds to load)
2 examples, 0 failures
Randomized with seed 4857
Press ENTER or type command to continue
Scanning of B:
Add another context to check for when B
has been scanned.
Add the context to the RSpec.describe 'checkout'
block.
The file changes to this;
RSpec.describe 'checkout' do
context 'when nothing has been scanned' do
it 'shows a total of zero' do
pricing_rules = :Rule
checkout = CheckOut.new(pricing_rules)
total = checkout.total
expect(total).to eq 0
end
end
context 'when A has been scanned' do
it 'shows the price of A' do
pricing_rules = :Rule
checkout = CheckOut.new(pricing_rules)
checkout.scan('A')
total = checkout.total
expect(total).to eq 50
end
end
context 'when B has been scanned' do
it 'shows the price of B' do
pricing_rules = :Rule
checkout = CheckOut.new(pricing_rules)
checkout.scan('B')
total = checkout.total
expect(total).to eq 30
end
end
end
When ⎵ + s
is pressed on the keyboard to only run this new test, the following error is displayed;
./bin/rspec spec/check_out_spec.rb:36
Run options: include {:locations=>{"./spec/check_out_spec.rb"=>[36]}}
Randomized with seed 53332
F
Failures:
1) checkout when B has been scanned shows the price of B
Failure/Error: expect(total).to eq 30
expected: 30
got: 50
(compared using ==)
# ./spec/check_out_spec.rb:44:in `block (3 levels) in <top (required)>'
Finished in 0.00643 seconds (files took 0.0565 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/check_out_spec.rb:37 # checkout when B has been scanned shows the price of A
Randomized with seed 53332
shell returned 1
Press ENTER or type command to continue
To fix this, make changes to the scan
method in the CheckOut
class;
class CheckOut
def initialize(pricing_rules)
@total = 0
end
def total
@total
end
def scan(item)
if item == 'A'
@total = 50
elsif item == 'B'
@total = 30
end
end
end
Now when press ⎵ + l
to run the last test, the test for scanning B
now passes as well;
./bin/rspec spec/check_out_spec.rb:40
Run options: include {:locations=>{"./spec/check_out_spec.rb"=>[40]}}
Randomized with seed 59538
.
Finished in 0.00059 seconds (files took 0.05165 seconds to load)
1 example, 0 failures
Randomized with seed 59538
Press ENTER or type command to continue
Scanning of C:
Add another context to check for when C
has been scanned.
Add the context to the RSpec.describe 'checkout'
block.
This is the context;
context 'when C has been scanned' do
it 'shows the price of C' do
pricing_rules = :Rule
checkout = CheckOut.new(pricing_rules)
checkout.scan('C')
total = checkout.total
expect(total).to eq 20
end
end
When + s
is pressed to run this new test, this error results;
./bin/rspec spec/check_out_spec.rb:59
Run options: include {:locations=>{"./spec/check_out_spec.rb"=>[59]}}
Randomized with seed 51710
F
Failures:
1) checkout when C has been scanned shows the price of C
Failure/Error: expect(total).to eq 20
expected: 20
got: 0
(compared using ==)
# ./spec/check_out_spec.rb:59:in `block (3 levels) in <top (required)>'
Finished in 0.00602 seconds (files took 0.05125 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/check_out_spec.rb:52 # checkout when C has been scanned shows the price of C
Randomized with seed 51710
shell returned 1
Press ENTER or type command to continue
To fix this, make changes to the CheckOut
class.
Do a check for item C
like so;
class CheckOut
def initialize(pricing_rules)
@total = 0
end
def total
@total
end
def scan(item)
if item == 'A'
@total = 50
elsif item == 'B'
@total = 30
elsif item == 'C'
@total = 20
end
end
end
And now when the test is run, it should be pass;
./bin/rspec spec/check_out_spec.rb:59
Run options: include {:locations=>{"./spec/check_out_spec.rb"=>[59]}}
Randomized with seed 2878
.
Finished in 0.00068 seconds (files took 0.05424 seconds to load)
1 example, 0 failures
Randomized with seed 2878
Press ENTER or type command to continue
Scanning of D:
Add another context to check for when D
has been scanned.
Add the context to the RSpec.describe 'checkout'
block.
This is the context;
context 'when D has been scanned' do
it 'shows the price of D' do
pricing_rules = :Rule
checkout = CheckOut.new(pricing_rules)
checkout.scan('D')
total = checkout.total
expect(total).to eq 15
end
end
When + s
is pressed to run this new test, this error results;
./bin/rspec spec/check_out_spec.rb:72
Run options: include {:locations=>{"./spec/check_out_spec.rb"=>[72]}}
Randomized with seed 61671
F
Failures:
1) checkout when D has been scanned shows the price of D
Failure/Error: expect(total).to eq 15
expected: 15
got: 0
(compared using ==)
# ./spec/check_out_spec.rb:72:in `block (3 levels) in <top (required)>'
Finished in 0.00622 seconds (files took 0.0561 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/check_out_spec.rb:65 # checkout when D has been scanned shows the price of D
Randomized with seed 61671
shell returned 1
Press ENTER or type command to continue
To fix this, make changes to the CheckOut
class.
Add an else
to check for item D
;
class CheckOut
def initialize(pricing_rules)
@total = 0
end
def total
@total
end
def scan(item)
if item == 'A'
@total = 50
elsif item == 'B'
@total = 30
elsif item == 'C'
@total = 20
else
@total = 15
end
end
end
And now when the test is run, it should be pass;
./bin/rspec spec/check_out_spec.rb:72
Run options: include {:locations=>{"./spec/check_out_spec.rb"=>[72]}}
Randomized with seed 38120
.
Finished in 0.00059 seconds (files took 0.05152 seconds to load)
1 example, 0 failures
Randomized with seed 38120
Press ENTER or type command to continue
Conclusion:
This concludes part 2.
In part 3, this will handled;
- refactoring to make the code better.
- taking the pricing rules into account
Shout out to Rob for his immense assistance on this and making it easy to comprehend.