SlideShare a Scribd company logo
1 of 93
Download to read offline
How BDD style Unit Testing
  helps you write better
         test code
       (and some caveat)


      @ihower at RubyKaigi 2011
      Ruby Taiwan & OptimisDev
About Me
•     Chang, Wen-Tien

     •   a.k.a. ihower

     •   http://ihower.tw

     •   http://twitter.com/ihower



    I’m ihower and here is my blog and t witter
    I have program ruby from 2006 for ruby on rails
    And I’m Yet another rubyist since rails.
From Taiwan



                                               3.5hrs



I come from Taiwan which is far away about 4hours flight
I’m sorry that I can’t speak Japanese, and English is not my native language
If I speak Chinese, I guess you will escape now.
So please forgive my english. I hope it’s simple to understand.
I work at Optimis International, which is an america company in Taipei
Ruby Taiwan
                             http://ruby.tw




Beside daily job, I’m the founder and organizer of Ruby Taiwan community, I found
the community since 2008.
RubyConf Taiwan 2011/8/26-27
                            http://rubyconf.tw




  We are organizing rubyconf taiwan now.
  The date is augest 26 and 27 and it open registration now.
  Welcome to Taiwan.
Last year photo. Nice small meeting room. pretty sweet.
Agenda

• Why Unit Testing?
• How to do unit test in BDD style?
• Some BDD caveat
Today’s agenda. There will be three part:
First, I will talk about why, then how to do, finally talk about some caveat.
How many people do
      unit test?

Before get into BDD, how many people here do unit test all the way?
Could you raise your hand?
How many people use
  BDD framework
     (RSpec)?
And how many people use rspec?
Two kinds of test:
                                                  Verification
           Unit Test                       Are we writing the code right?




      Customer Test                                Validation
          (Acceptance Test)              Are we writing the right software?


There are roughly t wo kinds of test:
Unit test and Customer test(or called Acceptance test)
Unit test is about verification, the question is are we writing the code right?
Customer test is about validation, the question is are we writing the right soft ware?
Two kinds of test:
                                        Test individual class and
           Unit Test                            method




      Customer Test                     Test functionality of the
          (Acceptance Test)                 over-all system

Unit test test individual class and method
And Customer Test test functionality of the over-all system
Today is all about
            Unit Testing

Today is all about unit testing
1. Why Unit Testing?

Let get started part one
1.Verification
                    Do we write the code right?




First, it does verification
How to verify this?There are three execution path

                   def correct_year_month(year, month)

                     if month > 12
                       if month % 12 == 0
                          year += (month - 12) / 12
                          month = 12
                       else
                          year += month / 12
                          month = month % 12
                      end
                     end

                     return [year, month]

                   end
For example, how to verify this simple if else code.
There are three execution path which means if you manually test
you need play it 3 times in different way
via UI?
via irb console?
Manually test is
  inefficient
Unit testing give us
instant coding feedback
           it "should return correct year and month" do
             correct_year_month(2011, 3).should == [2011, 3]
             correct_year_month(2011, 14).should == [2012,2]
             correct_year_month(2011, 24).should == [2012,12]
           end




automatic unit testing can give us instant feedback
you can test many times you want.
2.Check regression
Safety Net: when you add new feature and refactoring




test also check the regression
it’s a safety net when you add new feature or refactoring
It can give you confidence that you won’t break up any existed behavior
3.API design
    guide you write better API, especially test first.




third, Since test code is the client for your production code,
so if the test code is hard to write, it may means your API is not good.
Writing unit testing can guide you write better API, especially when you write
test first.
4.Documentation
          What the result should be?
Communication is the key for software development.




finally, uniting test can be your code documentation.
It can answer you what’s the class and method result should be?
Communication the key for successful soft ware development.
Brief Summary
•   Your code is not trivial:
    Automatic test can save your verify/debug time

•   Your code is not throwing way:
    Regression test

•   Test first: Guide you write better API

•   Tests as Documentation
2. How to do unit test
    in BDD style?
xUnit Framework
• Each test has four-phase:
 • Setup
 • Exercise
 • Verify (assertion)
 • Teardown
First, We use xUnit framework to test code.
Each test should be isolation and has four phase:
1. Setup Data
2. Exercise production code
3. Verify the result 4. Cleanup the data
Ruby Test::Unit
          class OrderTest < Test::Unit::TestCase

           def setup
         1   @order = Order.new
           end

             def test_order_amount
               assert_equal 0, @order.amount
             end     3                2

          end

The is the classical ruby test::unit code
Red 1 is setup
Red 2 is exercise
Red 3 is verify. We assert the result equal to zero
Minitest::Spec
         describe Order do

            before do
          1   @order = Order.new
            end

             it "should have default amount is 0" do
               @order.amount.must_equal 0
             end     2            3

         end

Here is the BDD style using minitest::spec
red 1 is setup
red 2 is exercise
red 3 is verify. the result must equal to zero
First impression
               about BDD

• Syntax is different
 • Like specification
 • More readable
So, what’s the first impression about bdd style?
Ok, the syntax is different, it looks like spec and may more readable
Other wise the structure is not much different
What’s BDD?
 • An improved xUnit Framework
 • Focus on clearly describe the expected
     behavior
 • The emphasis is Tests as Documentation
     rather than merely using tests for
     verification.
Let’s back to see what’s BDD means.
It’s not totally new test framework, it just an improved xUnit framework
It focus on describe the expected behavior
It emphasize tests as documentation, not just for verification.
Terminology changed
           New paradigm: Executable Specification



• “Test” becomes “Spec”
• “Assertion” becomes “Expectation”
• “test method” becomes “example” (RSpec)
• “test case” becomes “example group” (RSpec)
For correspond to the new paradigm: the test is the executable specification
The “test” becomes “spec”
“Assertion” becomes “Expectation”
Ruby BDD tools

 • RSpec
 • Minitest/Spec

In Ruby, there are some choices:
RSpec is the most powerful, has many features and many awesome syntax.
Minitest/spec is the Ruby 1.9 build-in xunit library. It’s simple, fast, and just
works!
Learn BDD style
 • It’s about syntax
  • syntax
  • syntax
  • syntax
Let’s learn how to write BDD style test code.
Basically, it’s just learn about syntax.
BDD style element (1)
     Context
one test case
                         describe Order do
                           # ...
                         end                            a class or
                                                          string
                         # or

                         describe "A Order" do
                           # ...
                         end




Instead of test case class, BDD style use “describe” block for one test case
It accept parameter which means the stuff you want to describe, usually a class
name or just description text.
Can be nested

                 describe Order do

                    describe "#amount" do
                        # ...                       #method means
                    end                             instance method

                    describe ".size" do
                        # ...
                    end
                                                .method means
                                                 class method
                 end


“describe” block can be nested.
And inner “describe” usually describe method.
Pound means instance method
dot means class method
In RSpec,
      alias_method :context, :describe
           1   describe Order do

               2 context "when initialized" do

                  3 describe "#amount" do
                      # ...
                    end

                  3 describe ".size" do
                      # ...
                    end

                  end

Is RSpec, it alsoend describe to context.
                  alias
it used to organize test code into different context.
BDD style element (2)
  Declarative test
one test method: it
        you can write test description in plain text

        describe Order do

          describe "#amount" do
            describe "when user is vip" do
              it "should discount five percent if total > 1000" do
                # ...
              end

                it "should discount ten percent if total > 10000" do
                  # ...
                end
              end

        end
Each test method is “it” block
And it accept one parameter which is description text
Setup method: before
           describe Order do

              before do
                @user = User.new( :is_vip => true )
                @order = Order.new( :user => @user )
              end

           end




the setup method is “before” block
nested before
             btw, the outer data will be shared, make the test faster

        describe Order do

       1   before do
             @user = User.new( :is_vip => true )
             @order = Order.new( :user => @user )
           end

           describe "#amount" do

           2 before do
               @order2 = Order.new( :user => @user )
             end

           end
“before” block also support nested
        end
More important, the outer setup data will be shard for all inside test methods.
Make the test faster since we need not create again every time.
https://github.com/citrusbyte/contest
                      class SomeTest < Test::Unit::TestCase
                        setup do
                          @value = 1
                        end

                        test "sample test" do
                          assert_equal 1, @value
                        end

                        context "a context" do
                          setup do
                            @value += 1
                          end

                          test "more tests" do
                            assert_equal 2, @value
                          end

                        end
There are library   which make
                      end        test/unit support context and declarative test ,
like contest
https://github.com/jm/context

              class UserTest < Test::Unit::TestCase

                context "A new User" do
                  before do
                    @user = User.first
                  end

                    test "should have the right full_name" do
                      assert_equal "Dude Man", @user.full_name
                    end

              end




Or context
Rails support declarative test
                 (but no nested context)

           class PostsControllerTest < ActionController::TestCase

             setup
               @post = posts(:one)
             end

             test "should show post" do
               get :show, :id => @post.id
               assert_response :success
             end

           end


Even rails, It supports declarative test syntax. It use “test” block
But no nested context.
BDD style element (3)
   Expectation
Expectation(Assertion)
              Minitest/Spec

     @order.amount.must_equal 1900
     @order.amount.wont_equal 2000
     lambda{ order.ship! }.must_raise NotPaidError




BDD style assertion is called expectation.
In menitest/spec, the methods are must_equal, wont_equal, must_raise
In unit/test, some people may confuse assert method that first parameter and
second parameter, which one is actual and which one is expect. But BDD style, it’s
impossible to confuse it.
Expectation(Assertion)
                  RSpec
 @order.amount.should == 1900
 @order.amount.should_not == 2000
 lambda{ order.ship! }.should_raise NotPaidError
 # or
 expect { order.ship! }.to raise_error(NotPaidError)




Here is rspec version. should equal and should_not equal
Matchy
                   https://github.com/jm/matchy


         x.should == 42
         y.length.should_not be(4)
         lambda { raise "FAIL" }.should raise_error




There is also library can make test/unit support bdd style expectation only.
BDD cares about
  the output
RSpec output :)
              Output (rspec)

                                                         Really nice code
                                                         documentation




RSpec does the output very well, you can see really nice code documentation
HTML format
Minitest Output :(




But I can’t not find how to generate code documentation in minitest/spec
require 'minitest/pride'
            # Show your testing pride!




I found there is a minitest/pride you can required! It may help format the output,
so I try it!
Very funny @_@




And here is the output....... very funny. Good job!
Use turn gem
gem 'minitest' # use gem version instead of stdlib
require 'minitest/spec'
require 'turn'

MiniTest::Unit.use_natural_language_case_names = true
MiniTest::Unit.autorun



Anyway, There is a gem called trun which used in Rails 3.1
It can generate nice test output for unit/test
So here I require it.
Bt w, I suggest you use the latest minitest gem version, not standard library. Since
the gem version is much new.
I totally agree tenderlove suggestion yesterday that we should move some
standard library into gem.
Minitest::Spec output :)




Here is the output, very nice.
Brief Summary
• Three BDD style elements:
 • context
 • declarative test
 • expectation
• test output can be code documentation
So...
Why Syntax Matters?
Your language shape how
       you think!
   Language will not limit you, but it does influence how you think.




   http://www.nytimes.com/2010/08/29/magazine/29language-t.html
For example:
test_datetime_format

# ruby/test/logger/test_logger.rb
class TestLogger < Test::Unit::TestCase

  def test_datetime_format
    dummy = STDERR
    logger = Logger.new(dummy)
    log = log_add(logger, INFO, "foo")
    assert_match(/^dddd-dd-ddTdd:dd:dd.s*d+ $/, log.datetime)
    logger.datetime_format = "%d%b%Y@%H:%M:%S"
    log = log_add(logger, INFO, "foo")
    assert_match(/^ddwwwdddd@dd:dd:dd$/, log.datetime)
    logger.datetime_format = ""
    log = log_add(logger, INFO, "foo")
    assert_match(/^$/, log.datetime)
  end

end


This is a test code from ruby core for Logger
it test datetime_format method
the same test in rubyspec
         # rubyspec/logger/logger/datetime_format_spec.rb
         describe "Logger#datetime_format" do
           # ...
           it "returns the date format used for the logs"
           it "returns nil logger is using the default date format"
         end

         describe "Logger#datetime_format=" do
           # ...

            it "sets the date format for the logs" do
              format = "%Y"
              @logger.datetime_format = "%Y"
              @logger.datetime_format.should == "%Y"
              @logger.add(Logger::WARN, "Test message")
              @log_file.rewind

              regex = /2[0-9]{3}.*Test message/
              @log_file.readlines.first.should =~ regex
            end

            it "follows the Time#strftime format"

           end
 This is the same test in rubyspec
 you can see it divide into many describe and it block.
In this case:
• Test::Unit version just do verify
• Spec version not only verify but also describe its
  behavior:
  •   It help us understand what’s the method should do

  •   It increases the test coverage
The BDD syntax guides
   you focus on the
  expected behavior
Emphasis on
Tests as Documentation
Rather than merely
  using tests for
    verification
3. BDD style caveat
1. Too magic?
Metaprogramming?

• The BDD framework using metaprograming
    should not be the problem.
• The problem is some (RSpec) advanced
    awesome syntax may make the test code hard
    to understand or not intuitive.
Metaprogramming implementation should be the problem.
If it is, then many ruby library is bad including rails.

The problem is some advanced awesome syntax may hard to understand.
implicit subject
                                    (RSpec)



              describe Order do

                    its(:status) { should == "New" }

              end


For example. RSpec has a feature callsd implict subject.
You can omit the receiver of expectation method.
It also has a syntax call its, its...... its....
well, hard to explain... let see another equal version
Equal to this version:

         describe Order do
           before do
             @order = Order.new
           end

            it "should have default status is New" do
              @order.status.should == "New"
            end

           end
oh.... I see...
its will covert Order instance and call its method

well, seems magic!
would like DRY?
         describe PostsController do
           describe "PUT #update" do
             before do
          1    @post = Factory(:post)
             end

              it "allows an author to edit a post" do
                sign_in @post.author
             2 put :update, :id => post.id, :body => "new content"

             3     response.should be_successful
                 end

              it "does not allow a non-author to edit a post" do
                sign_in Factory(:user)
             2 put :update, :id => post.id, :body => "new content"

             3     response.should be_forbidden
             end
           end
Another  example
         end      to test rails controller:
red 1 is setup part
red 2 is exercise
red 3 is verify

The red 2 exercise are almost the same, so some people may want to DRY.
But readable?
    describe PostsController do
      describe "PUT #update" do
    1 let(:post) { Factory(:post) }
            before do
              sign_in user
        2     put :update, :id => post.id, :body => "new content"
            end

            context "when logged in as post's author" do
              let(:user) { post.author }

               it "allows the post to be updated" do
            3    response.should be_success
               end
             end

            context "when logged in as another user" do
              let(:user) { Factory(:user) }

           it "does not allow the post to be updated" do
        3    response.should be_forbidden
           end
         end
So they move the code into before block
      end
and rspec has a feature called “let”, it’s a lazy and memorized   method for setup
    end
data.

Finally in the test method, Only left assertion: response.should be_success
Four-phase Test form is
 key to understand the
             test code
• Setup      Why?
             I think for test code:

• Exercise   four-phase test form is the
             key to understand.


• Verify (assertion)
             When I see one test method, I
             must need to figure out what’s
             the setup, exercise and verify.

• Teardown   So, it should be easy to trace.
2.English-like DSL?
http://pragdave.blogs.pragprog.com/pragdave/2008/03/
                 the-language-in.html



Second caveat is english-like DSL.
Dave Thomas has a nice article explain this problem.
“The language in a DSL should be the
   language of the domain, not the natural
language of the developer. “ by DaveThomas


He said...

so... To be english-like is not DSL’s purpose.
The easy to use and readable DSL API is the purpose
# Bacon
        it 'should have an object identity' do
          @ary.should.not.be.same_as Array.new
        end

                                         the be is just “self”




Let’s see one obvious example. This is a bacon test code.
There is a be method inside method chain, but it does nothing and just return self.

It existed only because we want to make it like english. Is it right?
RSpec matcher (1)
target.should be_true      # targer.should == true
target.should be_false     # targer.should == false
target.should be_nil       # targer.should == nil

target.should be_a_kind_of(Array)      # target.class.should == Array
target.should be_an_instance_of(Array) # target.class.should == Array




 On the other hand, RSpec has core feature called matcher for expectation.
 It also make the test code readable. In some way, It’s also very easy to use.

 like
 * be_true,
 * be_false
 * be_a_kind_of
RSpec matcher (2)
                  target.should respond_to(:foo)
                  # target.repond_to?(:foo).should == true

                  target.should have_key(:foo)
                  # target[:foo].should_not == nil

                  target.should include(4)
                  # target.include?(4).should == true

                  target.should have(3).items
                  # target.items.length == 3



There are more example like

* have_key
* include
RSpec matcher (3)
         target.should be_empty
         # target.empty?.should == true

         target.should be_blank
         # target.blank?.should == true

         target.should be_admin
         # target.admin?.should == true




any prefix be_ matcher will covert it to that method with question mark.
RSpec matcher is very
       powerful
    # Custom Matcher
    describe 9 do
      it "should be a multiple of 3" do
        9.should be_a_multiple_of(3)
        # (9 % 3).should == 0
      end
    end

    # RSpec supports custom matchers DSL
    RSpec::Matchers.define :be_a_multiple_of do |
    expected|
      match do |actual|
        actual % expected == 0
      end
    end

RSpec matcher is very powerful since it even provide DSL to define your custom
matcher which make the your test readable.
Some matchers I like,
     but some I dislike.
It becomes personal taste :|
3. Deep nested context?
       describe Order do

           before do
       1     @order = Order.new
           end

           describe "#amount" do

               before do
           1     @order2 = Order.new( :total => 2000)
               end

               describe "when user is vip" do
                 before do
               1   @user = User.new(:is_vip => true)
                 end

                 it "should discount five percent if total >= 1000" do
                   # ...
                 end
               end
         end
There are three
       end      nested context here. For the most inner test method, it has
three before block outside.
Deep nested is hateful
    It’s hard to understand what’s setup going on in sub-sub-sub-sub context




Deep nested context is hateful, It hard to trace the setup part when there is sub-
sub-sub-sub context
Four-phase Test form is
 key to understand the
             test code
• Setup      Again. Four-phase Test form:


• Exercise   Deep context make setup part
             hard to trace.


• Verify (assertion)
             That’s why Rails does not
             support nested context.


• Teardown   Rails team like flat test
             structure.
4. Too mockist?
• rspec-rails gem divides tests into
   model,controller,view,helper and encourages
   you use mocks.
• should_receive easily make people test
   implementation rather than result by default.
   Make your test fragile.

 RSpec ship with very nice mock feature,
 And RSpec-rails divides tests into four layer which encourage you use mocks.

 But mocks has many caveats too, It make the test fragile easily.
5.Performance penalty?

• minitest/spec performance is almost equal to
   test/unit. It’s really fast.
• RSpec performance is slower comparing to
   test/unit.
minitest/spec performance is pretty well, you need not to worry about it.

RSpec is slower, But when running test, I think the bottleneck is your
production code and the testing framework factor is not big problem.
Conclusion
yes, it’s not required...
• BDD testing framework is unlike
  ActiveRecord for SQL, Rails for web
  development. It does not “simplify” test. It’s
  not an abstract tool for testing.
• So, yes, It’s not required and some people
  think it’s unnecessary.
But it’s very valuable
  for your team!
• The BDD syntax guides you focus on
    the expected behavior, and increasing
    the test coverage.
• Emphasis on Tests as Documentation
    rather than merely using tests for
    verification.

It focus on describe the expected behavior and increase the test coverage
It emphasize tests as documentation, not just for verification.
Thanks for listening!
 Please tweet me if you have questions:

         @ihower
Reference
•   RSpec                    slides, ihower
    OSDC.TW 2011
•   xUnit Test Patterns
•   http://avdi.org/devblog/2011/04/07/rspec-is-for-
    the-literate/
•   http://objectreload.com/articles/2010/09/
    thoughts-on-testing-part-1.html

More Related Content

What's hot

Automation test framework with cucumber – BDD
Automation test framework with cucumber – BDDAutomation test framework with cucumber – BDD
Automation test framework with cucumber – BDD123abcda
 
Agile Testing Process
Agile Testing ProcessAgile Testing Process
Agile Testing ProcessIntetics
 
Unit testing & TDD concepts with best practice guidelines.
Unit testing & TDD concepts with best practice guidelines.Unit testing & TDD concepts with best practice guidelines.
Unit testing & TDD concepts with best practice guidelines.Mohamed Taman
 
Cypress - Best Practices
Cypress - Best PracticesCypress - Best Practices
Cypress - Best PracticesBrian Mann
 
Scrum master basics
Scrum master basics Scrum master basics
Scrum master basics Elad Sofer
 
Test automation - What? Why? How?
Test automation - What? Why? How?Test automation - What? Why? How?
Test automation - What? Why? How?Anand Bagmar
 
Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Lars Thorup
 
BDD WITH CUCUMBER AND JAVA
BDD WITH CUCUMBER AND JAVABDD WITH CUCUMBER AND JAVA
BDD WITH CUCUMBER AND JAVASrinivas Katakam
 
Transform Agile Development With Practical DevOps
Transform Agile Development With Practical DevOpsTransform Agile Development With Practical DevOps
Transform Agile Development With Practical DevOpsGaurav Sharma
 
Automated testing with Cypress
Automated testing with CypressAutomated testing with Cypress
Automated testing with CypressYong Shean Chong
 
BDD Selenium for Agile Teams - User Stories
BDD Selenium for Agile Teams - User StoriesBDD Selenium for Agile Teams - User Stories
BDD Selenium for Agile Teams - User StoriesSauce Labs
 

What's hot (20)

Automation test framework with cucumber – BDD
Automation test framework with cucumber – BDDAutomation test framework with cucumber – BDD
Automation test framework with cucumber – BDD
 
Cucumber presenation
Cucumber presenationCucumber presenation
Cucumber presenation
 
Agile Testing Process
Agile Testing ProcessAgile Testing Process
Agile Testing Process
 
Tdd and bdd
Tdd and bddTdd and bdd
Tdd and bdd
 
Unit testing & TDD concepts with best practice guidelines.
Unit testing & TDD concepts with best practice guidelines.Unit testing & TDD concepts with best practice guidelines.
Unit testing & TDD concepts with best practice guidelines.
 
Cypress testing
Cypress testingCypress testing
Cypress testing
 
Agile sdlc
Agile sdlcAgile sdlc
Agile sdlc
 
Cypress - Best Practices
Cypress - Best PracticesCypress - Best Practices
Cypress - Best Practices
 
Guide to Agile testing
Guide to Agile testingGuide to Agile testing
Guide to Agile testing
 
Scrum master basics
Scrum master basics Scrum master basics
Scrum master basics
 
Test automation - What? Why? How?
Test automation - What? Why? How?Test automation - What? Why? How?
Test automation - What? Why? How?
 
Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)
 
BDD WITH CUCUMBER AND JAVA
BDD WITH CUCUMBER AND JAVABDD WITH CUCUMBER AND JAVA
BDD WITH CUCUMBER AND JAVA
 
Transform Agile Development With Practical DevOps
Transform Agile Development With Practical DevOpsTransform Agile Development With Practical DevOps
Transform Agile Development With Practical DevOps
 
Scrum best practices
Scrum best practicesScrum best practices
Scrum best practices
 
Automated testing with Cypress
Automated testing with CypressAutomated testing with Cypress
Automated testing with Cypress
 
Introduction to TDD and BDD
Introduction to TDD and BDDIntroduction to TDD and BDD
Introduction to TDD and BDD
 
Test automation proposal
Test automation proposalTest automation proposal
Test automation proposal
 
Agile Methodology
Agile MethodologyAgile Methodology
Agile Methodology
 
BDD Selenium for Agile Teams - User Stories
BDD Selenium for Agile Teams - User StoriesBDD Selenium for Agile Teams - User Stories
BDD Selenium for Agile Teams - User Stories
 

Similar to BDD style Unit Testing

Beyond Testing: Specs and Behavior Driven Development
Beyond Testing: Specs and Behavior  Driven DevelopmentBeyond Testing: Specs and Behavior  Driven Development
Beyond Testing: Specs and Behavior Driven DevelopmentRabble .
 
It's all about behaviour, also in php - phpspec
It's all about behaviour, also in php - phpspecIt's all about behaviour, also in php - phpspec
It's all about behaviour, also in php - phpspecGiulio De Donato
 
2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD WorkshopWolfram Arnold
 
TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012Pietro Di Bello
 
TDD Walkthrough - Encryption
TDD Walkthrough - EncryptionTDD Walkthrough - Encryption
TDD Walkthrough - EncryptionPeterKha2
 
RSpec: What, How and Why
RSpec: What, How and WhyRSpec: What, How and Why
RSpec: What, How and WhyRatan Sebastian
 
Agile JavaScript Testing
Agile JavaScript TestingAgile JavaScript Testing
Agile JavaScript TestingScott Becker
 
Behavior Driven Development
Behavior Driven Development Behavior Driven Development
Behavior Driven Development Dhawal Joshi
 
Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013Brian Sam-Bodden
 
Testing Has Many Purposes
Testing Has Many PurposesTesting Has Many Purposes
Testing Has Many PurposesAlex Sharp
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven DevelopmentTung Nguyen Thanh
 
Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Gianluca Padovani
 
Don't let your tests slow you down
Don't let your tests slow you downDon't let your tests slow you down
Don't let your tests slow you downDaniel Irvine
 
Testing With Test::Class
Testing With Test::ClassTesting With Test::Class
Testing With Test::ClassCurtis Poe
 

Similar to BDD style Unit Testing (20)

Beyond Testing: Specs and Behavior Driven Development
Beyond Testing: Specs and Behavior  Driven DevelopmentBeyond Testing: Specs and Behavior  Driven Development
Beyond Testing: Specs and Behavior Driven Development
 
It's all about behaviour, also in php - phpspec
It's all about behaviour, also in php - phpspecIt's all about behaviour, also in php - phpspec
It's all about behaviour, also in php - phpspec
 
2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop
 
TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012
 
TDD Walkthrough - Encryption
TDD Walkthrough - EncryptionTDD Walkthrough - Encryption
TDD Walkthrough - Encryption
 
RSpec: What, How and Why
RSpec: What, How and WhyRSpec: What, How and Why
RSpec: What, How and Why
 
Agile JavaScript Testing
Agile JavaScript TestingAgile JavaScript Testing
Agile JavaScript Testing
 
Behavior Driven Development
Behavior Driven Development Behavior Driven Development
Behavior Driven Development
 
Rspec
RspecRspec
Rspec
 
Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013
 
Testing Has Many Purposes
Testing Has Many PurposesTesting Has Many Purposes
Testing Has Many Purposes
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven Development
 
Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Tdd is not about testing (OOP)
Tdd is not about testing (OOP)
 
BDD Primer
BDD PrimerBDD Primer
BDD Primer
 
Don't let your tests slow you down
Don't let your tests slow you downDon't let your tests slow you down
Don't let your tests slow you down
 
Tdd in practice
Tdd in practiceTdd in practice
Tdd in practice
 
Rspec
RspecRspec
Rspec
 
Testing With Test::Class
Testing With Test::ClassTesting With Test::Class
Testing With Test::Class
 
TDD and Getting Paid
TDD and Getting PaidTDD and Getting Paid
TDD and Getting Paid
 
Like SpecFlow
Like SpecFlowLike SpecFlow
Like SpecFlow
 

More from Wen-Tien Chang

⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨Wen-Tien Chang
 
Ruby Rails 老司機帶飛
Ruby Rails 老司機帶飛Ruby Rails 老司機帶飛
Ruby Rails 老司機帶飛Wen-Tien Chang
 
A brief introduction to Machine Learning
A brief introduction to Machine LearningA brief introduction to Machine Learning
A brief introduction to Machine LearningWen-Tien Chang
 
淺談 Startup 公司的軟體開發流程 v2
淺談 Startup 公司的軟體開發流程 v2淺談 Startup 公司的軟體開發流程 v2
淺談 Startup 公司的軟體開發流程 v2Wen-Tien Chang
 
RSpec on Rails Tutorial
RSpec on Rails TutorialRSpec on Rails Tutorial
RSpec on Rails TutorialWen-Tien Chang
 
ALPHAhackathon: How to collaborate
ALPHAhackathon: How to collaborateALPHAhackathon: How to collaborate
ALPHAhackathon: How to collaborateWen-Tien Chang
 
Git 版本控制系統 -- 從微觀到宏觀
Git 版本控制系統 -- 從微觀到宏觀Git 版本控制系統 -- 從微觀到宏觀
Git 版本控制系統 -- 從微觀到宏觀Wen-Tien Chang
 
Exception Handling: Designing Robust Software in Ruby (with presentation note)
Exception Handling: Designing Robust Software in Ruby (with presentation note)Exception Handling: Designing Robust Software in Ruby (with presentation note)
Exception Handling: Designing Robust Software in Ruby (with presentation note)Wen-Tien Chang
 
Exception Handling: Designing Robust Software in Ruby
Exception Handling: Designing Robust Software in RubyException Handling: Designing Robust Software in Ruby
Exception Handling: Designing Robust Software in RubyWen-Tien Chang
 
從 Classes 到 Objects: 那些 OOP 教我的事
從 Classes 到 Objects: 那些 OOP 教我的事從 Classes 到 Objects: 那些 OOP 教我的事
從 Classes 到 Objects: 那些 OOP 教我的事Wen-Tien Chang
 
Yet another introduction to Git - from the bottom up
Yet another introduction to Git - from the bottom upYet another introduction to Git - from the bottom up
Yet another introduction to Git - from the bottom upWen-Tien Chang
 
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩Wen-Tien Chang
 
Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介Wen-Tien Chang
 
A brief introduction to SPDY - 邁向 HTTP/2.0
A brief introduction to SPDY - 邁向 HTTP/2.0A brief introduction to SPDY - 邁向 HTTP/2.0
A brief introduction to SPDY - 邁向 HTTP/2.0Wen-Tien Chang
 
RubyConf Taiwan 2012 Opening & Closing
RubyConf Taiwan 2012 Opening & ClosingRubyConf Taiwan 2012 Opening & Closing
RubyConf Taiwan 2012 Opening & ClosingWen-Tien Chang
 
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean StartupWen-Tien Chang
 
那些 Functional Programming 教我的事
那些 Functional Programming 教我的事那些 Functional Programming 教我的事
那些 Functional Programming 教我的事Wen-Tien Chang
 
RubyConf Taiwan 2011 Opening & Closing
RubyConf Taiwan 2011 Opening & ClosingRubyConf Taiwan 2011 Opening & Closing
RubyConf Taiwan 2011 Opening & ClosingWen-Tien Chang
 

More from Wen-Tien Chang (20)

⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨
 
Ruby Rails 老司機帶飛
Ruby Rails 老司機帶飛Ruby Rails 老司機帶飛
Ruby Rails 老司機帶飛
 
A brief introduction to Machine Learning
A brief introduction to Machine LearningA brief introduction to Machine Learning
A brief introduction to Machine Learning
 
淺談 Startup 公司的軟體開發流程 v2
淺談 Startup 公司的軟體開發流程 v2淺談 Startup 公司的軟體開發流程 v2
淺談 Startup 公司的軟體開發流程 v2
 
RSpec on Rails Tutorial
RSpec on Rails TutorialRSpec on Rails Tutorial
RSpec on Rails Tutorial
 
RSpec & TDD Tutorial
RSpec & TDD TutorialRSpec & TDD Tutorial
RSpec & TDD Tutorial
 
ALPHAhackathon: How to collaborate
ALPHAhackathon: How to collaborateALPHAhackathon: How to collaborate
ALPHAhackathon: How to collaborate
 
Git 版本控制系統 -- 從微觀到宏觀
Git 版本控制系統 -- 從微觀到宏觀Git 版本控制系統 -- 從微觀到宏觀
Git 版本控制系統 -- 從微觀到宏觀
 
Exception Handling: Designing Robust Software in Ruby (with presentation note)
Exception Handling: Designing Robust Software in Ruby (with presentation note)Exception Handling: Designing Robust Software in Ruby (with presentation note)
Exception Handling: Designing Robust Software in Ruby (with presentation note)
 
Exception Handling: Designing Robust Software in Ruby
Exception Handling: Designing Robust Software in RubyException Handling: Designing Robust Software in Ruby
Exception Handling: Designing Robust Software in Ruby
 
從 Classes 到 Objects: 那些 OOP 教我的事
從 Classes 到 Objects: 那些 OOP 教我的事從 Classes 到 Objects: 那些 OOP 教我的事
從 Classes 到 Objects: 那些 OOP 教我的事
 
Yet another introduction to Git - from the bottom up
Yet another introduction to Git - from the bottom upYet another introduction to Git - from the bottom up
Yet another introduction to Git - from the bottom up
 
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
 
Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介
 
A brief introduction to SPDY - 邁向 HTTP/2.0
A brief introduction to SPDY - 邁向 HTTP/2.0A brief introduction to SPDY - 邁向 HTTP/2.0
A brief introduction to SPDY - 邁向 HTTP/2.0
 
RubyConf Taiwan 2012 Opening & Closing
RubyConf Taiwan 2012 Opening & ClosingRubyConf Taiwan 2012 Opening & Closing
RubyConf Taiwan 2012 Opening & Closing
 
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
 
Git Tutorial 教學
Git Tutorial 教學Git Tutorial 教學
Git Tutorial 教學
 
那些 Functional Programming 教我的事
那些 Functional Programming 教我的事那些 Functional Programming 教我的事
那些 Functional Programming 教我的事
 
RubyConf Taiwan 2011 Opening & Closing
RubyConf Taiwan 2011 Opening & ClosingRubyConf Taiwan 2011 Opening & Closing
RubyConf Taiwan 2011 Opening & Closing
 

Recently uploaded

Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...itnewsafrica
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFMichael Gough
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
Infrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsInfrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsYoss Cohen
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Jeffrey Haguewood
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesManik S Magar
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Kaya Weers
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Mark Simos
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...Karmanjay Verma
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 

Recently uploaded (20)

Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDF
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
Infrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsInfrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platforms
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 

BDD style Unit Testing

  • 1. How BDD style Unit Testing helps you write better test code (and some caveat) @ihower at RubyKaigi 2011 Ruby Taiwan & OptimisDev
  • 2. About Me • Chang, Wen-Tien • a.k.a. ihower • http://ihower.tw • http://twitter.com/ihower I’m ihower and here is my blog and t witter I have program ruby from 2006 for ruby on rails And I’m Yet another rubyist since rails.
  • 3. From Taiwan 3.5hrs I come from Taiwan which is far away about 4hours flight I’m sorry that I can’t speak Japanese, and English is not my native language If I speak Chinese, I guess you will escape now. So please forgive my english. I hope it’s simple to understand.
  • 4. I work at Optimis International, which is an america company in Taipei
  • 5. Ruby Taiwan http://ruby.tw Beside daily job, I’m the founder and organizer of Ruby Taiwan community, I found the community since 2008.
  • 6. RubyConf Taiwan 2011/8/26-27 http://rubyconf.tw We are organizing rubyconf taiwan now. The date is augest 26 and 27 and it open registration now. Welcome to Taiwan.
  • 7. Last year photo. Nice small meeting room. pretty sweet.
  • 8. Agenda • Why Unit Testing? • How to do unit test in BDD style? • Some BDD caveat Today’s agenda. There will be three part: First, I will talk about why, then how to do, finally talk about some caveat.
  • 9. How many people do unit test? Before get into BDD, how many people here do unit test all the way? Could you raise your hand?
  • 10. How many people use BDD framework (RSpec)? And how many people use rspec?
  • 11. Two kinds of test: Verification Unit Test Are we writing the code right? Customer Test Validation (Acceptance Test) Are we writing the right software? There are roughly t wo kinds of test: Unit test and Customer test(or called Acceptance test) Unit test is about verification, the question is are we writing the code right? Customer test is about validation, the question is are we writing the right soft ware?
  • 12. Two kinds of test: Test individual class and Unit Test method Customer Test Test functionality of the (Acceptance Test) over-all system Unit test test individual class and method And Customer Test test functionality of the over-all system
  • 13. Today is all about Unit Testing Today is all about unit testing
  • 14. 1. Why Unit Testing? Let get started part one
  • 15. 1.Verification Do we write the code right? First, it does verification
  • 16. How to verify this?There are three execution path def correct_year_month(year, month) if month > 12 if month % 12 == 0 year += (month - 12) / 12 month = 12 else year += month / 12 month = month % 12 end end return [year, month] end For example, how to verify this simple if else code. There are three execution path which means if you manually test you need play it 3 times in different way
  • 19. Manually test is inefficient
  • 20. Unit testing give us instant coding feedback it "should return correct year and month" do correct_year_month(2011, 3).should == [2011, 3] correct_year_month(2011, 14).should == [2012,2] correct_year_month(2011, 24).should == [2012,12] end automatic unit testing can give us instant feedback you can test many times you want.
  • 21. 2.Check regression Safety Net: when you add new feature and refactoring test also check the regression it’s a safety net when you add new feature or refactoring It can give you confidence that you won’t break up any existed behavior
  • 22. 3.API design guide you write better API, especially test first. third, Since test code is the client for your production code, so if the test code is hard to write, it may means your API is not good. Writing unit testing can guide you write better API, especially when you write test first.
  • 23. 4.Documentation What the result should be? Communication is the key for software development. finally, uniting test can be your code documentation. It can answer you what’s the class and method result should be? Communication the key for successful soft ware development.
  • 24. Brief Summary • Your code is not trivial: Automatic test can save your verify/debug time • Your code is not throwing way: Regression test • Test first: Guide you write better API • Tests as Documentation
  • 25. 2. How to do unit test in BDD style?
  • 26. xUnit Framework • Each test has four-phase: • Setup • Exercise • Verify (assertion) • Teardown First, We use xUnit framework to test code. Each test should be isolation and has four phase: 1. Setup Data 2. Exercise production code 3. Verify the result 4. Cleanup the data
  • 27. Ruby Test::Unit class OrderTest < Test::Unit::TestCase def setup 1 @order = Order.new end def test_order_amount assert_equal 0, @order.amount end 3 2 end The is the classical ruby test::unit code Red 1 is setup Red 2 is exercise Red 3 is verify. We assert the result equal to zero
  • 28. Minitest::Spec describe Order do before do 1 @order = Order.new end it "should have default amount is 0" do @order.amount.must_equal 0 end 2 3 end Here is the BDD style using minitest::spec red 1 is setup red 2 is exercise red 3 is verify. the result must equal to zero
  • 29. First impression about BDD • Syntax is different • Like specification • More readable So, what’s the first impression about bdd style? Ok, the syntax is different, it looks like spec and may more readable Other wise the structure is not much different
  • 30. What’s BDD? • An improved xUnit Framework • Focus on clearly describe the expected behavior • The emphasis is Tests as Documentation rather than merely using tests for verification. Let’s back to see what’s BDD means. It’s not totally new test framework, it just an improved xUnit framework It focus on describe the expected behavior It emphasize tests as documentation, not just for verification.
  • 31. Terminology changed New paradigm: Executable Specification • “Test” becomes “Spec” • “Assertion” becomes “Expectation” • “test method” becomes “example” (RSpec) • “test case” becomes “example group” (RSpec) For correspond to the new paradigm: the test is the executable specification The “test” becomes “spec” “Assertion” becomes “Expectation”
  • 32. Ruby BDD tools • RSpec • Minitest/Spec In Ruby, there are some choices: RSpec is the most powerful, has many features and many awesome syntax. Minitest/spec is the Ruby 1.9 build-in xunit library. It’s simple, fast, and just works!
  • 33. Learn BDD style • It’s about syntax • syntax • syntax • syntax Let’s learn how to write BDD style test code. Basically, it’s just learn about syntax.
  • 34. BDD style element (1) Context
  • 35. one test case describe Order do # ... end a class or string # or describe "A Order" do # ... end Instead of test case class, BDD style use “describe” block for one test case It accept parameter which means the stuff you want to describe, usually a class name or just description text.
  • 36. Can be nested describe Order do describe "#amount" do # ... #method means end instance method describe ".size" do # ... end .method means class method end “describe” block can be nested. And inner “describe” usually describe method. Pound means instance method dot means class method
  • 37. In RSpec, alias_method :context, :describe 1 describe Order do 2 context "when initialized" do 3 describe "#amount" do # ... end 3 describe ".size" do # ... end end Is RSpec, it alsoend describe to context. alias it used to organize test code into different context.
  • 38. BDD style element (2) Declarative test
  • 39. one test method: it you can write test description in plain text describe Order do describe "#amount" do describe "when user is vip" do it "should discount five percent if total > 1000" do # ... end it "should discount ten percent if total > 10000" do # ... end end end Each test method is “it” block And it accept one parameter which is description text
  • 40. Setup method: before describe Order do before do @user = User.new( :is_vip => true ) @order = Order.new( :user => @user ) end end the setup method is “before” block
  • 41. nested before btw, the outer data will be shared, make the test faster describe Order do 1 before do @user = User.new( :is_vip => true ) @order = Order.new( :user => @user ) end describe "#amount" do 2 before do @order2 = Order.new( :user => @user ) end end “before” block also support nested end More important, the outer setup data will be shard for all inside test methods. Make the test faster since we need not create again every time.
  • 42. https://github.com/citrusbyte/contest class SomeTest < Test::Unit::TestCase setup do @value = 1 end test "sample test" do assert_equal 1, @value end context "a context" do setup do @value += 1 end test "more tests" do assert_equal 2, @value end end There are library which make end test/unit support context and declarative test , like contest
  • 43. https://github.com/jm/context class UserTest < Test::Unit::TestCase context "A new User" do before do @user = User.first end test "should have the right full_name" do assert_equal "Dude Man", @user.full_name end end Or context
  • 44. Rails support declarative test (but no nested context) class PostsControllerTest < ActionController::TestCase setup @post = posts(:one) end test "should show post" do get :show, :id => @post.id assert_response :success end end Even rails, It supports declarative test syntax. It use “test” block But no nested context.
  • 45. BDD style element (3) Expectation
  • 46. Expectation(Assertion) Minitest/Spec @order.amount.must_equal 1900 @order.amount.wont_equal 2000 lambda{ order.ship! }.must_raise NotPaidError BDD style assertion is called expectation. In menitest/spec, the methods are must_equal, wont_equal, must_raise In unit/test, some people may confuse assert method that first parameter and second parameter, which one is actual and which one is expect. But BDD style, it’s impossible to confuse it.
  • 47. Expectation(Assertion) RSpec @order.amount.should == 1900 @order.amount.should_not == 2000 lambda{ order.ship! }.should_raise NotPaidError # or expect { order.ship! }.to raise_error(NotPaidError) Here is rspec version. should equal and should_not equal
  • 48. Matchy https://github.com/jm/matchy x.should == 42 y.length.should_not be(4) lambda { raise "FAIL" }.should raise_error There is also library can make test/unit support bdd style expectation only.
  • 49. BDD cares about the output
  • 50. RSpec output :) Output (rspec) Really nice code documentation RSpec does the output very well, you can see really nice code documentation
  • 52. Minitest Output :( But I can’t not find how to generate code documentation in minitest/spec
  • 53. require 'minitest/pride' # Show your testing pride! I found there is a minitest/pride you can required! It may help format the output, so I try it!
  • 54. Very funny @_@ And here is the output....... very funny. Good job!
  • 55. Use turn gem gem 'minitest' # use gem version instead of stdlib require 'minitest/spec' require 'turn' MiniTest::Unit.use_natural_language_case_names = true MiniTest::Unit.autorun Anyway, There is a gem called trun which used in Rails 3.1 It can generate nice test output for unit/test So here I require it. Bt w, I suggest you use the latest minitest gem version, not standard library. Since the gem version is much new. I totally agree tenderlove suggestion yesterday that we should move some standard library into gem.
  • 56. Minitest::Spec output :) Here is the output, very nice.
  • 57. Brief Summary • Three BDD style elements: • context • declarative test • expectation • test output can be code documentation
  • 59. Your language shape how you think! Language will not limit you, but it does influence how you think. http://www.nytimes.com/2010/08/29/magazine/29language-t.html
  • 61. test_datetime_format # ruby/test/logger/test_logger.rb class TestLogger < Test::Unit::TestCase def test_datetime_format dummy = STDERR logger = Logger.new(dummy) log = log_add(logger, INFO, "foo") assert_match(/^dddd-dd-ddTdd:dd:dd.s*d+ $/, log.datetime) logger.datetime_format = "%d%b%Y@%H:%M:%S" log = log_add(logger, INFO, "foo") assert_match(/^ddwwwdddd@dd:dd:dd$/, log.datetime) logger.datetime_format = "" log = log_add(logger, INFO, "foo") assert_match(/^$/, log.datetime) end end This is a test code from ruby core for Logger it test datetime_format method
  • 62. the same test in rubyspec # rubyspec/logger/logger/datetime_format_spec.rb describe "Logger#datetime_format" do # ... it "returns the date format used for the logs" it "returns nil logger is using the default date format" end describe "Logger#datetime_format=" do # ... it "sets the date format for the logs" do format = "%Y" @logger.datetime_format = "%Y" @logger.datetime_format.should == "%Y" @logger.add(Logger::WARN, "Test message") @log_file.rewind regex = /2[0-9]{3}.*Test message/ @log_file.readlines.first.should =~ regex end it "follows the Time#strftime format" end This is the same test in rubyspec you can see it divide into many describe and it block.
  • 63. In this case: • Test::Unit version just do verify • Spec version not only verify but also describe its behavior: • It help us understand what’s the method should do • It increases the test coverage
  • 64. The BDD syntax guides you focus on the expected behavior
  • 65. Emphasis on Tests as Documentation
  • 66. Rather than merely using tests for verification
  • 67. 3. BDD style caveat
  • 69. Metaprogramming? • The BDD framework using metaprograming should not be the problem. • The problem is some (RSpec) advanced awesome syntax may make the test code hard to understand or not intuitive. Metaprogramming implementation should be the problem. If it is, then many ruby library is bad including rails. The problem is some advanced awesome syntax may hard to understand.
  • 70. implicit subject (RSpec) describe Order do its(:status) { should == "New" } end For example. RSpec has a feature callsd implict subject. You can omit the receiver of expectation method. It also has a syntax call its, its...... its.... well, hard to explain... let see another equal version
  • 71. Equal to this version: describe Order do before do @order = Order.new end it "should have default status is New" do @order.status.should == "New" end end oh.... I see... its will covert Order instance and call its method well, seems magic!
  • 72. would like DRY? describe PostsController do describe "PUT #update" do before do 1 @post = Factory(:post) end it "allows an author to edit a post" do sign_in @post.author 2 put :update, :id => post.id, :body => "new content" 3 response.should be_successful end it "does not allow a non-author to edit a post" do sign_in Factory(:user) 2 put :update, :id => post.id, :body => "new content" 3 response.should be_forbidden end end Another example end to test rails controller: red 1 is setup part red 2 is exercise red 3 is verify The red 2 exercise are almost the same, so some people may want to DRY.
  • 73. But readable? describe PostsController do describe "PUT #update" do 1 let(:post) { Factory(:post) } before do sign_in user 2 put :update, :id => post.id, :body => "new content" end context "when logged in as post's author" do let(:user) { post.author } it "allows the post to be updated" do 3 response.should be_success end end context "when logged in as another user" do let(:user) { Factory(:user) } it "does not allow the post to be updated" do 3 response.should be_forbidden end end So they move the code into before block end and rspec has a feature called “let”, it’s a lazy and memorized method for setup end data. Finally in the test method, Only left assertion: response.should be_success
  • 74. Four-phase Test form is key to understand the test code • Setup Why? I think for test code: • Exercise four-phase test form is the key to understand. • Verify (assertion) When I see one test method, I must need to figure out what’s the setup, exercise and verify. • Teardown So, it should be easy to trace.
  • 75. 2.English-like DSL? http://pragdave.blogs.pragprog.com/pragdave/2008/03/ the-language-in.html Second caveat is english-like DSL. Dave Thomas has a nice article explain this problem.
  • 76. “The language in a DSL should be the language of the domain, not the natural language of the developer. “ by DaveThomas He said... so... To be english-like is not DSL’s purpose. The easy to use and readable DSL API is the purpose
  • 77. # Bacon it 'should have an object identity' do @ary.should.not.be.same_as Array.new end the be is just “self” Let’s see one obvious example. This is a bacon test code. There is a be method inside method chain, but it does nothing and just return self. It existed only because we want to make it like english. Is it right?
  • 78. RSpec matcher (1) target.should be_true # targer.should == true target.should be_false # targer.should == false target.should be_nil # targer.should == nil target.should be_a_kind_of(Array) # target.class.should == Array target.should be_an_instance_of(Array) # target.class.should == Array On the other hand, RSpec has core feature called matcher for expectation. It also make the test code readable. In some way, It’s also very easy to use. like * be_true, * be_false * be_a_kind_of
  • 79. RSpec matcher (2) target.should respond_to(:foo) # target.repond_to?(:foo).should == true target.should have_key(:foo) # target[:foo].should_not == nil target.should include(4) # target.include?(4).should == true target.should have(3).items # target.items.length == 3 There are more example like * have_key * include
  • 80. RSpec matcher (3) target.should be_empty # target.empty?.should == true target.should be_blank # target.blank?.should == true target.should be_admin # target.admin?.should == true any prefix be_ matcher will covert it to that method with question mark.
  • 81. RSpec matcher is very powerful # Custom Matcher describe 9 do it "should be a multiple of 3" do 9.should be_a_multiple_of(3) # (9 % 3).should == 0 end end # RSpec supports custom matchers DSL RSpec::Matchers.define :be_a_multiple_of do | expected| match do |actual| actual % expected == 0 end end RSpec matcher is very powerful since it even provide DSL to define your custom matcher which make the your test readable.
  • 82. Some matchers I like, but some I dislike. It becomes personal taste :|
  • 83. 3. Deep nested context? describe Order do before do 1 @order = Order.new end describe "#amount" do before do 1 @order2 = Order.new( :total => 2000) end describe "when user is vip" do before do 1 @user = User.new(:is_vip => true) end it "should discount five percent if total >= 1000" do # ... end end end There are three end nested context here. For the most inner test method, it has three before block outside.
  • 84. Deep nested is hateful It’s hard to understand what’s setup going on in sub-sub-sub-sub context Deep nested context is hateful, It hard to trace the setup part when there is sub- sub-sub-sub context
  • 85. Four-phase Test form is key to understand the test code • Setup Again. Four-phase Test form: • Exercise Deep context make setup part hard to trace. • Verify (assertion) That’s why Rails does not support nested context. • Teardown Rails team like flat test structure.
  • 86. 4. Too mockist? • rspec-rails gem divides tests into model,controller,view,helper and encourages you use mocks. • should_receive easily make people test implementation rather than result by default. Make your test fragile. RSpec ship with very nice mock feature, And RSpec-rails divides tests into four layer which encourage you use mocks. But mocks has many caveats too, It make the test fragile easily.
  • 87. 5.Performance penalty? • minitest/spec performance is almost equal to test/unit. It’s really fast. • RSpec performance is slower comparing to test/unit. minitest/spec performance is pretty well, you need not to worry about it. RSpec is slower, But when running test, I think the bottleneck is your production code and the testing framework factor is not big problem.
  • 89. yes, it’s not required... • BDD testing framework is unlike ActiveRecord for SQL, Rails for web development. It does not “simplify” test. It’s not an abstract tool for testing. • So, yes, It’s not required and some people think it’s unnecessary.
  • 90. But it’s very valuable for your team!
  • 91. • The BDD syntax guides you focus on the expected behavior, and increasing the test coverage. • Emphasis on Tests as Documentation rather than merely using tests for verification. It focus on describe the expected behavior and increase the test coverage It emphasize tests as documentation, not just for verification.
  • 92. Thanks for listening! Please tweet me if you have questions: @ihower
  • 93. Reference • RSpec slides, ihower OSDC.TW 2011 • xUnit Test Patterns • http://avdi.org/devblog/2011/04/07/rspec-is-for- the-literate/ • http://objectreload.com/articles/2010/09/ thoughts-on-testing-part-1.html