问个 rspec 的问题,当我不用 rspec-expectation 时,它是怎么判断一个 case 是成功还是失败呢?
describe Object do
it "how to determin this is fine or wrong?" do
false
#true
end
end
false 或者 true 都是 pass 的。
@leomayleomay
@heliang7
我这里ruby 1.8.6
没assert
, 不是core
里的吗 ?
我就是想知道it
方法是如何判断成功和失败的,现在能肯定不是基于return value
.
那是异常?或者assert
(居然在ruby
中不是关键字)?或者其他什么东西。
@hisea 谢谢,你这种写法是对的。能再帮忙解答下我 3 楼的问题吗,水平有限,到翻 rspec 的源码,没找到答案。
describe Object do
it "how to determin this is fine or wrong" do
true.should be_true
end
it "{} works?" { true.should be_true }
end
我一开始以为describe
和it
是某个类或模块提供的方法,通过继承或者mixin
所以上面代码能工作了。但后面想想,不对呀,仅上面这段代码,不需要require
或者include
什么东西,它也能工作的好好的。
那么上面这段代码,应该是类似于rspec
的配置文件,rspec 会读取它并解释它(你们说的 DSL?),或者有个类似于eval
的动态执行的东西,总之暂时还不懂。
撇下这些不管,我现在很奇怪,那个rspec
是怎样根据do .. end
块中的内容,来判断一个 testcase 是真还是假呢?
现在肯定不是靠返回值,因为如果ture.should be_true
返回值是true
的话,和我直接写true
结果应该一样,但是我直接写false
它还是成功;
assert
又不是ruby
关键字,也不像;
那是通过抛异常?那个啥shoud
,还有be_ture
,是个啥子东西嘛!
你说对了,rspec 是一个 DSL.
assert 不是 rspec 里面的,xUnit 之类的会有 assert. Ruby 的话是 Test::Unit
不过道理都是一样的。
测试里面其实测试并不是返回 true 或者 false 的。
测试比简单的 true 和 false 更复杂一些。
同一个测试可以因为不同的原因 fail。 expectation 就是这个样子的,在一个测试里面 expect 或者说‘期待’一个或者多个东西是成立的。
it "how to determin this is fine or wrong" do
true.should be_true
2.should == 3
end
be_true 和 ==3 是 matcher,就是具体来检验你期待的东西成不成立的 rspec 有很多https://github.com/rspec/rspec-expectations/tree/master/lib/rspec/matchers/built_in
大部分都是 ruby 语言的 matcher.
shoulda 是一个 gem,提供了 rails 的 matcher,比如
describe Post do
it { should belong_to(:user) }
it { should validate_presence_of(:title) }
end
it 是 dsl 的一部分,其目的是让 test 看起来像一个说明或者是规范,或者说是 specification,这就是 rspec 名称的由来。
it 其实是一个方法。用来定义一个 example
example 可以想象成一个 testcase,不过稍微复杂些的是有些 context 的东西。 具体定义在这里https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/example_group.rb
其中最关键的一行是这个 examples << RSpec::Core::Example.new(self, desc, options, block)
吧 block 也就是你的 true.should be_true 传到一个新的 example 里面去了。
其他的 should, describe 等等,都是方法,rspec 是元编程的超级合身。从上面的源码就能看出,跟 it 不同名的功能几乎一样的方法有很多
# Defines an example within a group.
define_example_method :example
# Defines an example within a group.
#
# @see example
define_example_method :it
# Defines an example within a group.
# This is here primarily for backward compatibility with early versions
# of RSpec which used `context` and `specify` instead of `describe` and
# `it`.
define_example_method :specify
# Shortcut to define an example with `:focus` => true
define_example_method :focus, :focused => true, :focus => true
# Shortcut to define an example with `:focus` => true
define_example_method :focused, :focused => true, :focus => true
# Shortcut to define an example with :pending => true
define_example_method :pending, :pending => true
# Shortcut to define an example with :pending => 'Temporarily disabled with xexample'
define_example_method :xexample, :pending => 'Temporarily disabled with xexample'
# Shortcut to define an example with :pending => 'Temporarily disabled with xit'
define_example_method :xit, :pending => 'Temporarily disabled with xit'
# Shortcut to define an example with :pending => 'Temporarily disabled with xspecify'
define_example_method :xspecify, :pending => 'Temporarily disabled with xspecify'
楼主应该是不明白 should 是怎么工作的吧。 其实很简单,should 就是个 mixin 进去的 method,在里面计算 self 的值是否符合 expectatin,如果不符合就告诉测试环境(总有方法让它获得环境的)——“这里有一个 assertion 失败”,基本原理就是这样
@hisea 非常感谢。学到很多。 我混淆了rspec和rspec-core。我以为should之类的东西,应该是rspec-expectation里面的,那我写最简单的case,应该只用到了rspec-core,没用到rspec-expectation,所以纠结should是哪里来的。 上次去shanghai ruby Tuesday,弄混了rake和rack,今天又弄混一个,尴尬。 打算好好研究下rake,bundle,rspec这些小而精的工具的源码。再次感谢。