Slide 1

Slide 1 text

How I Learned to Stop Worrying and Like RSpec Bryce Kerley Miami Ruby Brigade Sept. 15, 2014

Slide 2

Slide 2 text

Preemptive Answers Yes, the slides will be online Yes, the code samples are online

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Please Test Your Important Code

Slide 5

Slide 5 text

I Like RSpec • Testing, TDD, and Agile • Minitest features • How I got to RSpec • RSpec philosophy • RSpec practice

Slide 6

Slide 6 text

Agile If you’re not sure what to do yet, do the simplest thing that could possibly work. http://www.artima.com/intv/simplest3.html

Slide 7

Slide 7 text

Testing Defines “work”

Slide 8

Slide 8 text

Testing Tells you when you break stuff

Slide 9

Slide 9 text

Forget Manual Testing Error-prone Doesn’t test all interactions Especially ones that are a pain

Slide 10

Slide 10 text

Test-Driven Development 1. Write failing test for feature 2. Write code to pass the failing test 3. Write code to pass tests you broke 4. Clean up your mess

Slide 11

Slide 11 text

Test-driven development is about not being afraid to try something. If you break it, you’ll know, and you’re a `git checkout` away from fixing it.

Slide 12

Slide 12 text

I Like RSpec • Testing, TDD, and Agile • Minitest features • How I got to RSpec • RSpec philosophy • RSpec practice

Slide 13

Slide 13 text

Conway's Game of Life • Grid of cells • Live cells with two or three neighbors stay alive • Dead cells with three neighbors come to life

Slide 14

Slide 14 text

Five Minutes of Minitest require 'minitest/autorun' ! class CellTest < Minitest::Test def test_counts_neighbors c = Cell.new(0, 0) assert_equal 0, c.neighbors ! c2 = Cell.new(1, 0) assert_equal 1, c.neighbors end ! def test_comes_to_life end def test_stays_alive end end

Slide 15

Slide 15 text

Minitest in Rails require 'test_helper' ! class PostTest < ActiveSupport::TestCase test 'a post has many comments' do p = Post.create assert_empty p.comments c = Comment.create post: p refute_empty p.comments end end

Slide 16

Slide 16 text

Minitest with Nesting Minitest::Test can’t Minitest::Spec can

Slide 17

Slide 17 text

Minitest with Mocking def test_comes_to_life @board = Minitest::Mock.new @board.expect :neighbors, 3 ! c = Cell.new(@board, 0, 0) ! assert c.become_alive? end

Slide 18

Slide 18 text

I Like RSpec • Testing, TDD, and Agile • Minitest features • How I got to RSpec • RSpec philosophy • RSpec practice

Slide 19

Slide 19 text

basho My Day Job Three years at Basho! We’re hiring!

Slide 20

Slide 20 text

Riak Ruby Client • Started January 2010 • RSpec from the beginning • I took over May 2013 • 5833 lines of RSpec tests As of Thursday we have 5750 lines of tests, but we ripped out a bunch of complex systems.

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

My Transition Copying and modifying existing specs My first commit on riak-ruby-client had a zillion assignments in a `before` block.

Slide 23

Slide 23 text

My Transition Finding good documentation It’s the rspec organization on “relishapp”, link later.

Slide 24

Slide 24 text

My Transition Practice and review All my RSpec work was code-reviewed and commented on, which helped.

Slide 25

Slide 25 text

My Transition Second nature Today, I’d rather write RSpec for new work even knowing my previous complaints about it.

Slide 26

Slide 26 text

I Like RSpec • Testing, TDD, and Agile • Minitest features • How I got to RSpec • RSpec philosophy • RSpec practice

Slide 27

Slide 27 text

https://twitter.com/srbaker/status/345035925232955393

Slide 28

Slide 28 text

RSpec Philosophy • Write yellow skeleton specs • Implement an expectation so it’s red • Fulfill an expectation to make it green

Slide 29

Slide 29 text

Conway's Game with RSpec describe Cell do subject { described_class.new(0, 0) } ! it 'comes to life appropriately' it 'stays alive appropriately’ ! it 'counts neighbors' do expect(subject.neighbors).to eq 0 ! c2 = described_class.new(1, 0) expect(subject.neighbors).to eq 1 end end Spec group Skeletons Spec Expectation

Slide 30

Slide 30 text

RSpec in Rails require 'rails_helper' ! RSpec.describe Post, :type => :model do subject{ described_class.create } ! it 'has many comments' do expect(subject.comments).to be_empty c = Comment.create post: subject expect(subject.comments).to_not be_empty end end

Slide 31

Slide 31 text

Batteries Included • rspec-core: contexts, syntax • rspec-expectations: basically assertions • rspec-mocks: mocks, doubles, stubs

Slide 32

Slide 32 text

RSpec Philosophy RSpec is a product

Slide 33

Slide 33 text

I Like RSpec • Testing, TDD, and Agile • Minitest features • How I got to RSpec • RSpec philosophy • RSpec practice

Slide 34

Slide 34 text

Easy to Install • Not Rails: rspec --init • Rails: gem 'rspec-rails' in your Gemfile

Slide 35

Slide 35 text

The Syntax it{ is_expected.to be } subject(:post){ Post.new } expect(something.else).to eq 5 expect(somebody).to be_lovable allow(some_mock).to receive :method expect{ something.method }.to raise_error

Slide 36

Slide 36 text

The Syntax • A confusing mish-mash of spaces, underscores, dots, parens, braces, symbols, strings • Oh, and words

Slide 37

Slide 37 text

Let & Subject describe “CRDTs" do let(:bucket) { random_bucket } ! describe 'counters' do subject { Riak::Crdt::Counter.new bucket, random_key } ! it 'asks for and accepts a returned body' do other = Riak::Crdt::Counter.new(subject.bucket, subject.key) end end end

Slide 38

Slide 38 text

Let & Subject • let defines a variable only when you need it

Slide 39

Slide 39 text

Let & Subject class Turn def initialize puts "ACTUALLY BEING INITIALIZED" end end ! describe Turn do let(:turn){ Turn.new } ! it "might not get initialized" do expect(5).to eq 5 end ! it "is only initialized on use" do expect(turn).to be_a Turn end end

Slide 40

Slide 40 text

Let & Subject • subject defines a variable named “subject” only when you need it • Is implicitly defined to described_class.new • Allows implicit usage with it { is_expected… }

Slide 41

Slide 41 text

Let & Subject class Board def cromulent? true end end ! describe Board do it { is_expected.to be } it { is_expected.to be_a Board } it { is_expected.to be_cromulent } end

Slide 42

Slide 42 text

Quick Boolean Matchers • Quickly verify any question? methods that take no arguments: • expect(my_object).to be_cromulent • Passes if cromulent? returns true-y

Slide 43

Slide 43 text

Tagging & Focus Tagging allows subsets of tests to be run

Slide 44

Slide 44 text

Tagging & Focus describe 'Secure Protobuffs’ do ! describe 'without security enabled on Riak', no_security: true do it 'connects normally without authentication configured' do … ! describe 'with security enabled on Riak', yes_security: true do it 'connects normally with authentication configured' do These tests are mutually exclusive; they require server settings to be toggled and local configuration settings to match. I use tags to control which set runs.

Slide 45

Slide 45 text

Tagging & Focus • focus is a tag with quick syntax • skip is metadata with quick syntax • “describe” to “fdescribe” or “xdescribe” • “it” to “fit” or “xit” • rspec ./spec/some_specs/… -t focus

Slide 46

Slide 46 text

Customizing & Promode • Put a .rspec file in your project root --format documentation --color

Slide 47

Slide 47 text

Promode

Slide 48

Slide 48 text

I Like RSpec • Testing, TDD, and Agile • Minitest features • How I got to RSpec • RSpec philosophy • RSpec practice

Slide 49

Slide 49 text

Please Test Test-driven development makes your project better

Slide 50

Slide 50 text

Minitest is Good Minitest comes with Ruby and it's good at getting the job done

Slide 51

Slide 51 text

Bryce and RSpec I started with RSpec because I had to I got good with RSpec because I enjoyed it

Slide 52

Slide 52 text

RSpec Philosophy Everything you need to test behavior of objects If it’s hard to do with RSpec, consider if it’s the right thing to do.

Slide 53

Slide 53 text

RSpec Practice Start with skeletons Describe behavior Make it pass

Slide 54

Slide 54 text

Thanks Bryce Kerley [email protected] https://twitter.com/bonzoesc https://github.com/bkerley

Slide 55

Slide 55 text

Docs and References https://pinboard.in/u:bryce/t:rspec-miamirb/ https://relishapp.com/rspec/ http://rspec.info http://rdoc.info/gems/minitest/frames https://github.com/bkerley/rspec-miamirb/branches