RSPEC中Expect和should表达式的示例

来源:互联网 发布:成都 大数据 招聘 编辑:程序博客网 时间:2024/06/05 04:01

EXPECT Basic usage

Here’s an example using rspec-core:

rubyRSpec.describe Order do it "sums the prices of the items in its line items" do order = Order.new order.add_entry(LineItem.new(:item => Item.new( :price => Money.new(1.11, :USD) ))) order.add_entry(LineItem.new(:item => Item.new( :price => Money.new(2.22, :USD), :quantity => 2 ))) expect(order.total).to eq(Money.new(5.55, :USD)) endend

The describe and it methods come from rspec-core. TheOrder,LineItem, Item and Money classes would be fromyour code. The last line of the exampleexpresses an expected outcome. Iforder.total == Money.new(5.55, :USD), thenthe example passes. If not, it fails with a message like:

expected: #<Money @value=5.55 @currency=:USD>     got: #<Money @value=1.11 @currency=:USD>

Built-in matchers

Equivalence

ruby

expect(actual).to eq(expected) # passes if actual == expected

expect(actual).to eql(expected) # passes if actual.eql?(expected)

expect(actual).not_to eql(not_expected) # passes if not(actual.eql?(expected))


Note: The new expect syntax no longer supports the== matcher.

Identity

ruby

expect(actual).to be(expected) # passes if actual.equal?(expected)

expect(actual).to equal(expected) # passes if actual.equal?(expected)

Comparisons

ruby

expect(actual).to be > expected

expect(actual).to be >= expected

expect(actual).to be <= expected

expect(actual).to be < expected

expect(actual).to be_within(delta).of(expected)

Regular expressions

ruby

expect(actual).to match(/expression/)

Note: The new expect syntax no longer supports the=~ matcher.

Types/classes

ruby

expect(actual).to be_an_instance_of(expected) # passes if actual.class == expected

expect(actual).to be_a(expected) # passes if actual.is_a?(expected)

expect(actual).to be_an(expected) # an alias for be_a

expect(actual).to be_a_kind_of(expected) # another alias

Truthiness

ruby

expect(actual).to be_truthy # passes if actual is truthy (not nil or false)

expect(actual).to be true # passes if actual == true

expect(actual).to be_falsy # passes if actual is falsy (nil or false)

expect(actual).to be false # passes if actual == false

expect(actual).to be_nil # passes if actual is nil

expect(actual).to_not be_nil # passes if actual is not nil

Expecting errors

ruby

expect { ... }.to raise_error

expect { ... }.to raise_error(ErrorClass)

expect { ... }.to raise_error("message")

expect { ... }.to raise_error(ErrorClass, "message")

Expecting throws

ruby

expect { ... }.to throw_symbol

expect { ... }.to throw_symbol(:symbol)

expect { ... }.to throw_symbol(:symbol, 'value')

Yielding

```rubyexpect { |b| 5.tap(&b) }.to yield_control # passes regardless of yielded args

expect {byield_if_true(true, &b) }.to yield_with_no_args # passes only if no args are yieldedexpect {b5.tap(&b) }.to yield_with_args(5)expect {b5.tap(&b) }.to yield_with_args(Fixnum)expect {b“a string”.tap(&b) }.to yield_with_args(/str/)

expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3)expect { |b| { :a => 1, :b => 2 }.each(&b) }.to yield_successive_args([:a, 1], [:b, 2])```

Predicate matchers

ruby

expect(actual).to be_xxx # passes if actual.xxx?expect(actual).to have_xxx(:arg) # passes if actual.has_xxx?(:arg)

Ranges (Ruby >= 1.9 only)

ruby

expect(1..10).to cover(3)

Collection membership

```ruby

expect(actual).to include(expected)

expect(actual).to start_with(expected)

expect(actual).to end_with(expected)

expect(actual).to contain_exactly(individual, items)# …which is the same as:expect(actual).to  match_array( expected_array ) ```

Examples

ruby

expect([1, 2, 3]).to include(1)

expect([1, 2, 3]).to include(1, 2)

expect([1, 2, 3]).to start_with(1)

expect([1, 2, 3]).to start_with(1, 2)

expect([1, 2, 3]).to end_with(3)

expect([1, 2, 3]).to end_with(2, 3)

expect({:a => 'b'}).to include(:a => 'b')

expect("this string").to include("is str")

expect("this string").to start_with("this")

expect("this string").to end_with("ring")

expect([1, 2, 3]).to contain_exactly(2, 3, 1)

expect([1, 2, 3]).to match_array([3, 2, 1])


Compound Matcher Expressions

You can also create compound matcher expressions usingand oror:

ruby

expect(alphabet).to start_with("a").and end_with("z")

expect(stoplight.color).to eq("red").or eq("green").or eq("yellow")

Composing Matchers

Many of the built-in matchers are designed to take matchers asarguments, to allow you to flexibly specify only the essentialaspects of an object or data structure. In addition, all of thebuilt-in matchers have one or more aliases that provide betterphrasing for when they are used as arguments to another matcher.

Examples

```ruby

expect { k += 1.05 }.to change { k }.by( a_value_within(0.1).of(1.0) )

expect { s = “barn” }.to change { s } .from( a_string_matching(/foo/) ) .to( a_string_matching(/bar/) )

expect([“barn”, 2.45]).to contain_exactly( a_value_within(0.1).of(2.5), a_string_starting_with(“bar”))

expect([“barn”, “food”, 2.45]).to end_with( a_string_matching(“foo”), a_value > 2)

expect([“barn”, 2.45]).to include( a_string_starting_with(“bar”) )

expect(:a => “food”, :b => “good”).to include(:a => a_string_matching(/foo/))

hash = { :a => { :b => [“foo”, 5], :c => { :d => 2.05 } }}

expect(hash).to match( :a => { :b => a_collection_containing_exactly( a_string_starting_with(“f”), an_instance_of(Fixnum) ), :c => { :d => (a_value < 3) } })

expect { |probe| [1, 2, 3].each(&probe)}.to yield_successive_args( a_value < 2, 2, a_value > 2 )```

Usage outside rspec-core

You always need to load rspec/expectations even if you only want to use one part of the library:

ruby

require 'rspec/expectations'

Then simply include RSpec::Matchers in any class:

```ruby

class MyClass include RSpec::Matchers

  def do_something(arg)

    expect(arg).to be > 0

    # do other stuff

  end

end```















should and should_not syntax

From the beginning RSpec::Expectations provided should and should_not methodsto define expectations on any object. In version 2.11expect method wasintroduced which is now the recommended way to define expectations on an object.

Why switch over from should to expect

Fix edge case issues

should and should_not work by being added to every object. However, RSpecdoes not own every object and cannot ensure they work consistently on every object.In particular, they can lead to surprising failures when used with BasicObject-subclassedproxy objects.

expect avoids these problems altogether by not needing to be available on all objects.

Unification of block and value syntaxes

Before version 2.11 expect was just a more readable alternative for blockexpectations. Since version 2.11expect can be used for both block and valueexpectations.

expect(actual).to eq(expected)expect { ... }.to raise_error(ErrorClass)

Seehttp://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntaxFor a detailed explanation

One-liners

The one-liner syntax supported byrspec-core usesshould even whenconfig.syntax = :expect. It reads better than the alternative, and does notrequire a global monkey patch:

describe User do  it { should validate_presence_of :email }end

Using either expect or should or both

By default, both expect and should syntaxes are available. In the future,the default may be changed to only enable theexpect syntax.

If you want your project to only use any one of these syntaxes, you can configureit:

RSpec.configure do |config|  config.expect_with :rspec do |c|    c.syntax = :expect             # disables `should`    # or    c.syntax = :should             # disables `expect`    # or    c.syntax = [:should, :expect]  # default, enables both `should` and `expect`  endend

SeeRSpec::Expectations::Syntax#expectfor more information.

Usage

The should and should_not methods can be used to define expectations on anyobject.

actual.should eq expectedactual.should be > 3[1, 2, 3].should_not include 4

Using Built-in matchers

Equivalence

actual.should     eq(expected)  # passes if actual == expectedactual.should     == expected   # passes if actual == expectedactual.should_not eql(expected) # passes if actual.eql?(expected)

Note: we recommend the eq matcher over== to avoid Ruby's "== in auseless context" warning when the== matcher is used anywhere but thelast statement of an example.

Identity

actual.should     be(expected)    # passes if actual.equal?(expected)actual.should_not equal(expected) # passes if actual.equal?(expected)

Comparisons

actual.should be >  expectedactual.should be >= expectedactual.should be <= expectedactual.should be <  expectedactual.should be_within(delta).of(expected)

Regular expressions

actual.should match(/expression/)actual.should =~ /expression/

Types/classes

actual.should     be_an_instance_of(expected)actual.should_not be_a_kind_of(expected)

Truthiness

actual.should be_true  # passes if actual is truthy (not nil or false)actual.should be_false # passes if actual is falsy (nil or false)actual.should be_nil   # passes if actual is nil

Predicate matchers

actual.should     be_xxx         # passes if actual.xxx?actual.should_not have_xxx(:arg) # passes if actual.has_xxx?(:arg)

Ranges (Ruby >= 1.9 only)

(1..10).should cover(3)

Collection membership

actual.should include(expected)actual.should start_with(expected)actual.should end_with(expected)

Examples

[1,2,3].should       include(1)[1,2,3].should       include(1, 2)[1,2,3].should       start_with(1)[1,2,3].should       start_with(1,2)[1,2,3].should       end_with(3)[1,2,3].should       end_with(2,3){:a => 'b'}.should   include(:a => 'b')"this string".should include("is str")"this string".should start_with("this")"this string".should end_with("ring")
相较来说应该使用expect更多一些。原因:

因为expect的实现侵入性比较低,expect方法会返回一个代理对象,上面绑定了一些可以用来进行断言的方法。

should的实现是将should一类的方法直接注入到所有的对象里,破坏性比较高。如果你自己定义了一些和

should一类同名的方法就悲剧了。





 require ‘spec_helper’:目的是加载’spec/spec_helper.rb’文件中的RSpec配置,运行时需要。
describe()方法:
      我们用describe()方法定义一个测试用例组,describe()方法的参数可以是我们要测试的对象(如例中的People),可以是一个字符串,用来描述该组,describe方法后的字符串所描述的内容可以对应一个用户故事。
      注意describe()方法是可以嵌套的,两个describe()方法衔接起来可以更细化一个用户故事,如上边的里面的describe()方法内就表示:”People have enough money pay for house”。
it()方法:
      我们用it()方法定义一个具体的测试用例(在RSpec中,称一个测试用例为一个example)。其后的字符串为该方法的参数,用来描述一个具体的场景,it方法体就是我们对系统在该场景下的行为的定义。
      It()方法和describe()方法衔接起来,可以完整的描述一个系统行为,以上边的最后的一个测试用例为:”People have enough money pay for house should travel ”。
context()方法:
      Context()方法和describe()方法的作用一样,不同点在于describe倾向于描述我们的测试对象,而context()方法倾向于用字符串描述用户故事。
before()和after():
      这两个方法很多测试框架都支持,需要说明的是这两个方法的参数,例子中为符号’:each’,表明对于每一个测试用例,先执行 before()方法中的代码,用例完成后执行after()方法中的代码,若参数为’:all’,则表示在所有的测试用例执行之前,先执行 before()方法中的代码,所有的用例完成后执行after()方法中的代码。
      RSpec还提供around()方法,暂不懂其用法,之后的报告中补上。
帮助方法:
      所谓的帮助方法就是把多个测试用例中重复的操作抽出作为一个公用的方法,提高代码重用度。如例子中的work_hard()方法。
共享行为:
      系统的某一个行为是很多场景下都具有的,那么我们可以把它定义为一个共享行为,我们通过share_examples_for()方法 定义共享行为,使用it_behaves_like()方法共享定义过的系统行为,如例子中的share_examples_for “any people”, it_behaves_like “any people”。
pending()方法:
      我们确定系统拥有一个行为,但是还没有具体定义,这时我们可以将该行为使用pending()方法来设置该行为为待定义,其后的字符串参数将在生成的报告中显示。
      pending()方法的另外一种用法就是,当一个测试用例失败时,我们可以利用pending方法设置其为一个待修复的bug,方法体内包含使用例失败的代码。例如最后一个测试用例的内容













The rspec-core gem installs an rspec executable. Run therspec command with
the --help flag to see the available options:

rspec --help

Getting started

Begin with a very simple example that expresses some basic desired behaviour.

# game_spec.rbRSpec.describe Game do  describe "#score" do    it "returns 0 for an all gutter game" do      game = Game.new      20.times { game.roll(0) }      expect(game.score).to eq(0)    end  endend

Run the example and watch it fail.

$ rspec game_spec.rb   uninitialized constant Object::Game (NameError)

Now write just enough code to make it pass.

# game_spec.rbrequire './game'...
# game.rbclass Game  def roll(pins)  end  def score    0  endend

Run the example and bask in the joy that is green.

$ rspec game_spec.rb --color --format docGame  #score    returns 0 for all gutter gameFinished in 0.00057 seconds1 example, 0 failures

0 0
原创粉丝点击