You've been using RSpec for a while, you know how to write tests, but you’re not sure you're getting the most from it. This is a quick run through of some of the lesser known, more advanced features of RSpec.
information about an example RSpec.describe "Athing", this_is_metadata: "Hi!" do context this_is_metadata: "I'll override the top one" do end it also_has_meta_data: "I'll have both keys" do end end
conditionally include code, or run hooks RSpec.configure do |config| config.include SomeModule, type: :awesome config.before :example, type: :awesome do # all the things end end
ordering RSpec.configure do |config| config.register_ordering :global do |examples| acceptance, unit = examples.partition { |ex| ex.metadata[:acceptance] } unit.shuffle + acceptance.shuffle end end
do expect(response.status).to eq(200) expect(response.headers).to include("Content-Type" => "application/json") expect(response.body).to eq('{"message":"Success"}') end end
expectations as one expectation • Compound matchers combine multiple assertions into one expectation • Consider an acceptance test that is checking a JSON response • Do we hard code a massive expected JSON response?
present an easy way to create custom matchers def have_detail fragment a_hash_including( 'something' => array_including(hash_including(fragment)) ) end
fashion • You can combine normal matchers using and and/or or • Any matcher supporting values_match? and === expect( my_json ).to have_detail(id: 1).and have_detail(id: 2)
be a block diffable # failed matchers will attempt to diff expected / actual description { "..." } failure_message { "..." } failure_message_when_negated { "..." } chain :another_thing, { "..." } # new, allows you to chain multiple matchs end
failure_message to be defined. • Optionally diffable? (requiring expected and actual) • Optionally supports_block_expectations? expects_call_stack_jump?
find failures... (0.17102 seconds) Starting bisect with 1 failing example and 9 non-failing examples. Checking that failure(s) are order-dependent... failure appears to be order-dependent Round 1: bisecting over non-failing examples 1-9 .. ignoring examples 6-9 (0.32943 seconds) Round 2: bisecting over non-failing examples 1-5 .. ignoring examples 4-5 (0.3154 seconds) Round 3: bisecting over non-failing examples 1-3 .. ignoring example 3 (0.2175 seconds) Bisect aborted! The most minimal reproduction command discovered so far is:
@output = output end def example_failed notification @output.puts "Bad times baz, we broke the build." end def example_passed notification @output.puts "Good news everyone!" end end