新手问题 RSpec 和 Capypara

ryan · 2013年06月05日 · 最后由 Ryan 回复于 2013年06月06日 · 3912 次阅读

最近在用 rspec 写测试脚本,发现 controller 的测试脚本写的好蛋疼,不是 template missing 就是不符合 expectation。。。难道 controller 脚本一定也要配合 view 来用的嘛?连 post 和 delete 这种请求都必须有 template。。。

所以想问问,有必要写 controller 的 rspec 嘛? capypara 是不是可以替换写 controller 和 view 的 rpsec。 感觉 capypara 更加只管,rspec 写 controller 都是模拟请求但是有时又会不符合 expectation

#controller
    def log_in
        admin=Admin.find_by_name(params[:name])
        unless admin.nil?
            admin=admin.authenticate(params[:password])
            if admin==false
                # wrong password,login again
                # redirect_to sign_in_admins_url
            else
                session[:admin]=admin.name
                redirect_to root_path
            end
        end
    end

#rspec
    describe "Post request for admins" do
        it "should log_in with right name and password" do
            # admin=FactoryGirl.build(:admin)
            post :log_in,name:"ryan",password:"123456"
            controller.params[:name].should=="ryan"
            controller.params[:password].should=="123456"
            # session[:admin].should eq 'ryan'
            response.should redirect_to root_path
        end
    end

如上就是正在面临的一个很蛋疼的问题,rspec 的判定一直都在两个错误里徘徊,template missing 和 response redirect_to "test/sign_in/path",expected root_path

unless admin.nil?

如果 admin 为空的时候,渲染了什么呢?

controller 有 if 判断的,就需要注意了,很难写测试。不如把逻辑移到 modal 层来测试。

匿名 #4 2013年06月05日

#1 楼 @Rei 直接说 unless 之后还有另外一个逻辑不就得了?真烦这种以为自己提前知道点,就以为“导师”的行为。

#1 楼 @Rei 对哦。。。我没给他加 unless 后的逻辑。可是其实我下面这段测试代码,是发送了一条正确的登陆请求,用户名和密码都是对的,那他应该是进 root_path 才对啊。

#3 楼 @xds2000 这样岂不是很蛋疼,controller 不可能永远没 if 啊,view 里都可以有 if。。。那我是不是可以放弃 controller rpsec 测试,只用 rspec 测试 model,controller 交给 capypara 才测试呢?

#5 楼 @Ryan 因为你有几条代码是注释掉的,不同的组合情况下会有不同的错误,就顶楼的代码来说,FactoryGirl 这行被注释了,所以应该找不到 admin。

#7 楼 @Rei 没明白你的意思,在 rspec 里面,admin 这个对象并不需要,因为 log_in 方法没有参数传递,由 action 里面的代码,应该是发送 post 请求和两个 params 就好了呀

capypara 作为 rspec 的插件用来写集成测试或者验收测试的:Request Spec/ Feature Spec, 不能取代单元测试

#8 楼 @Ryan 每次执行 case 的时候数据库是空的,action 里面找不到 admin。

#9 楼 @SharpX 那在开发中是否有必要坚持对 controller 用 rspec 做测试?比如我提到的 template missing,很多情况下,诸如 put ,delete, post 请求是没有相对应的 view,都是嵌入在其他的 view 里面。要是这样的话,每次测试上述几个请求相关的 action,岂不是很蛋疼。。。

#10 楼 @Rei rake db:test:prepare 是不是可以让测试通过数据库的查询?还是说必须得先用测试脚本往数据库插条数据,比如Factory_Gril.create(:admin),然后就可以让他过了呢?

#12 楼 @Ryan 每个 case 都清空的,这是为了排除旧数据影响测试结果。

#13 楼 @Rei 原来是这样。。。所以想要通过测试,进入 else 那段,就得在测试里先造数据对吗?

#14 楼 @Ryan 对的。有 before(:each) 这样的前置钩子给多个 case 准备数据。

#11 楼 @Ryan model controller request 是要测试的,不一定非要断言模版吧,你看看 expect 有很多东西的,如:expect(response).to redirect_to(@user)

#15 楼 @Rei 原来如此!多谢,这下思路清晰了。昨天查了很长时间 rspec 文档,都没找到相关的信息。

#16 楼 @SharpX 使用 expect 就不会造成 template missing 的错误吗?你的代码同样也有redirect_to,那和response.should redirect_to有什么样的区别呢?

#18 楼 @Ryan 你不写expect(response).to render_template("index") ,从哪来的 template missing ?

如果真有,说明代码需要 Refactor,这正是测试的作用

#19 楼 @SharpX 这个我明白啊。问题是,我用response.should就会有 template missing,但是 expect 方法可行,他们两个难道对结果判定是不一样的?

如果一个 action 最终执行的是默认 render 又没有对应模板,程序本身是会抛 template missing 异常的,无关测试。

if admin==false

这一处也是引起错误的分支。

#21 楼 @Rei 原来是这样。明白了。

刚开始由于搞不清是逻辑写错还是测试写错,所以比较痛苦。但是目前要坚持写多一点测试,这样你会发现程序运行起来跟你想的不一样。

#23 楼 @Rei 嗯,我是想这个项目既是一次练习,同时也是一次完整的项目,之前帮朋友建个网站,懒得写测试,都是通过开浏览器直接看效果。。。结果经常是遇到些有时有,有时无的 bug。。修好了一会儿又出现了。。- -

#25 楼 @jhjguxin 已收藏这个网站,确实很多有用的东西

需要 登录 后方可回复, 如果你还没有账号请 注册新账号