Rails测试《八》实战功能测试functional test22014-03-15今天继续我们的功能测试实战。项目还是:blog,大家可以从github或者gitcafe中获取项目源码。先来介绍一个断言assert_difference(expression, difference = 1, message = nil, &block)http://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html中比较详细的介绍。再一次强烈推荐http://api.rubyonrails.org/,还有http://ruby-doc.org/,还有http://apidock.com/,还有http://guides.rubyonrails.org/。这四个工具网站,真是好啊,谁用谁知道。assert_difference的英文解释是Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.直译的话就是测试两个数值的区别。哪两个数值呢,就是expression的数值。怎么变成一个了?不要着急,一个是block执行之前,一个是block执行之后。意译一下就是比较expression的数值在block执行前后的差,看这个差是否是difference 参数指定的值,这个参数是个可选参数,默认值是1。也可以理解为,block执行之后的expression值 - block执行之前的expression值,看这个差值是否等于difference 指定的值,默认差值为1。我们先来个简单例子说明一下。就拿项目中的添加post来举例,对应的controller的代码如下:
def create @category = Category.find(params[:post][:category_id]) params[:post].delete(:category_id) @post = @category.posts.build(params[:post]) @post.user = current_user @post.tag_ids = params[:tag_ids] if @post.save! flash[:notice] = "post was created successfully"redirect_to admin_posts_path elseflash.now[:notice] = "create post failed"render :newend end
添加成功之后会跳转到posts列表,失败的话,就保留在new这个页面。当然了,测试添加可以有很多方法。比如说添加之后,查询一下,看看是否存在。如果有标题唯一之类的验证,也可以再次添加相同的post,然后看看是否会提示已经存在。或者验证添加之后是否跳转到posts列表,是否输出正确添加的flash信息。今天我们就是为了讲解assert_difference这个断言,前面说过了,这个断言用来判断block前后的expression的差。再添加一篇post之后,post的个数会增加一,我们就用这个断言来验证添加是否成功。在test/functional/admin/posts_controller_test.rb文件中敲入下面的代码。
require "test_helper" class Admin::PostsControllerTest < ActionController::TestCaseinclude FactoryGirl::Syntax::Methods def test_should_create_post_successfully user = FactoryGirl.create(:user_valid) category = FactoryGirl.create(:category_valid) article = FactoryGirl.build(:post_valid) tag = FactoryGirl.build(:tag_valid) assert_difference("Post.count") dopost :create, {:post=>{:category_id=>category.id,:title=>article.title,:slug=>article.slug,:summary=>article.summary,:content=>article.content},:tag_ids => [tag.id]}, {:user_id => user.id} endassert_redirected_to admin_posts_path(assigns(:posts))endend