View
12
Download
0
Category
Preview:
Citation preview
RSpec
Based on the book “Effective Testing with RSpec 3”
RSpec
● RSpec is a productive Ruby test framework● Use natural (English) language to define tests● Support the Behaviour Driven Development● Support you to write test that:
○ Pays for the cost of writing and running it○ Helps you to design your code○ Helps you finding errors in your code
RSpec GEMS
● RSpec is made of three independent Ruby Gems○ RSpec::Core is the overall test infrastructure that runs
your specs○ RSpec::Expectations provides a readable, powerful
syntax for checking properties of your code○ RSpec::Mocks makes it easy to isolate the code you’re
testing from the rest of the system
Setup
Install a recent ruby version: $ rvm install 2.4.0
Install bundler: $ gem install bundler
Create a new folder for your project: $ mkdir my-project && cd my-project
Create a Gemfile with the following content:
Run bundler $ bundle install
First RSpec
● Let’s create a bowling game!
● To design it, we basically describe a bowling game and its features
○ Describe a normal bowling game
○ It has 10 pins
○ It allows players to hit the available pins
○ It computes the score based on the sequence of plays
First RSpec
Setup rspec: $ rspec --init
Create the Bowling class in lib/bowling.rb file with the following content:
First RSpec
Run the test: $ rspec
Create a rspec for the Bowling class in spec/bowling_spec.rb file with the following content:
First RSpec
● Implement the missing code and run the test again. It should pass =)● If you intend to make improvements to your code structure, you can do it
safely now● This is how TDD cycle works
RSpec Structure
● Each spec file has the specifications of the desired behaviour of your code● RSpec.describe block creates an example group that defines what you’re
testing (i.e. bowling)● The it block is an example of the bowling use (similar to a test case)● The expect verifies an expected outcome (similar to assertion)
RSpec Structure
● Each spec file has the specifications of the desired behaviour of your code● RSpec.describe block creates an example group that defines what you’re
testing (i.e. bowling)● The it block is an example of the bowling use (similar to a test case)● The expect verifies an expected outcome (similar to assertion)
It reads almost like spoken
English
More examples
● The following code describes how to add a new player to the bowling game
● As you write more specs, you’ll find yourself repeating setup code● You can share setup across examples through:
○ RSpec hooks run automatically at specific times during testing○ Helper methods are regular Ruby methods; you control when they run○ RSpec’s let construct removes some of the gotchas around helper
methods
RSpec Hook
● before hook adds a block that will run automatically before each example
● The setup code is shared across specs, but the individual Bowling instance is not
RSpec Hook
● There are three types of hooks in RSpec○ before - defines a block of code to be run before a set of examples○ after - defines a block of code to be run after a set of examples, even if
the example fails○ around - part of the hook runs before the example, and part runs after
Helper Methods
● Hooks will run for all examples, even if it’s not necessary
● Instead, you may write helper methods and call it where you need
Sharing Objects with let
● let defines a binding name (bowling) to the result of a computation (the block)
● RSpec will run the block the first time any example calls bowling
RSpec context block
● When you use RSpec on a real-world project, you’ll build up a suite of many examples
● To improve our spec code and output, we can group a set of related examples and their setup code together with a common description
RSpec context block
The output tells us exactly what behavior is failing:
Running spec tips
Output with documentation format $ rspec --format documentation
List the top time-waster examples $ rspec --profile 2
Run specific specs in a folder $ rspec spec/unit
Run specific specs in a file $ rspec spec/unit/specific_spec.rb
Run specific example in a file $ rspec spec/unit/specific_spec.rb:25
Run specific example by name $ rspec -e milk -fd
Exploring RSpec::Expectations
● Expectations express what you expect to be true at a specific point in your code
● The primary goal of RSpec::Expectations is clarity● Try reading the following examples out loud
Parts of an Expectation
The syntax of a expectation consist of three main parts:
Subject - the thing you’re testing; i.e., an instance of a Ruby class
Parts of an Expectation
The syntax of a expectation consist of three main parts:
Subject - the thing you’re testing; i.e., an instance of a Ruby class
Matcher - an object which specifies what you expect to be true about the subject, and provides the pass/fail logic
Parts of an Expectation
The syntax of a expectation consist of three main parts:
Subject - the thing you’re testing; i.e., an instance of a Ruby class
Matcher - an object which specifies what you expect to be true about the subject, and provides the pass/fail logic
(Optionally) - a custom failure message
Matchers - Equality and Identity
● Identity: e.g., two references to one object
● Value equality: two objects of compatible types with the same meaning; e.g., the integer 42 and the floating-point number 42.0
Matchers - Truthiness
● The objects false and nil are both treated as false● Everything else is treated as true
Matchers - Truthiness
● The objects false and nil are both treated as false● Everything else is treated as true
If you want to specify that a value is precisely equal to true or false:
Matchers - Operator Comparisons
● You can use the comparison operators implemented by objects
Matchers - Higher-Order
● Higher-order matchers are matchers that you can pass other matchers into● With this technique, you can build up composed matchers that specify exactly
the behavior you want
Matchers - start_with, end_with and all
● Useful when you care about the contents of a string or collection
Matchers - match
● If you call JSON or XML APIs, you often end up with deeply nested arrays and hashes
● For this purpose, you can use match rathern than eq
Matchers - Mutation
● It’s common for external actions—such as submitting a Web form—to change some state inside the system
● The change matcher helps you specify these sorts of mutations by:
1. Run your change block and store the result, array.size , as the before value
2. Run the code under test, array << 43. Run your change block a second time
and store the result, array.size, as the after value
4. Pass the spec if the before and after values are different
Matchers - Mutation with details
● The change matcher offers an easy way to give details about the change
Matchers - Others
● Ranges:
● A predicate is a method that answers a question with boolean answer, usually ends with a question mark. I.E., empty?
● RSpec supports dynamic matchers with predicate methods
Subject
● The subject method defines how to build the object we’re testing● RSpec gives us is_expected as shorthand for expect(subject)
RSpec
http://www.relishapp.com/rspec/rspec-expectations/docshttp://rspec.info/https://github.com/rspec/rspec-rails
Recommended