zoukankan      html  css  js  c++  java
  • Ruby on rails开发从头来(windows)(二十七) 测试驱动开发

    在敏捷开发的实践中,测试驱动是少不了的。这篇来看看在rails中的一个测试驱动开发的例子。

    在前面我们编写并进行了一些单元测试和功能测试,现在,我们的客户突然要求添加一个功能:系统的每个用户都可以对商品进行查询。

     我们先初步的画了一些草图,来整理我们的思路和设计,然后开始写代码。对于具体的实现,我们已经有了大致的思路,但是如果有更多的反馈信息的话会有助于我们走在正确的道路上。我们会在深入到代码之前,编写测试代码。考虑我们的代码将怎样工作,确定一些规约,当测试通过,你的代码就OK了。

    现在,我们来考虑一下查询功能的测试,应该由哪个controller来控制查询操作呢?用户和管理员都可以进行查询操作,我们可以在store_controller.rb或者admin_controller.rb中添加一个search()Action,但是这里我们添加一个SearchController,并且含有一个方法search。在rails命令行执行命令:

    depot>ruby script/generate controller Search search

     

    我们看到,在app/controllerstest/functional目录下已经生成了对应的文件。但是现在我们并不关心SearchControllersearch方法的实现,我们关心的是在测试时我们所期望看到的结果。现在添加测试代码,在test/functional/search_controller_test.rb中添加test_search方法:

    我们首先想到的是调用searchAction,然后判断是否得到了响应:

    get :search, :title => "Pragmatic Version Control"

    assert_response :success

     

    根据之前的草图,我们应该在页面上显示一个flash信息,所以我们要判断flash信息的文本,以及是否显示了正确的页面:

    assert_equal "Found 1 product(s).", flash[:notice]

    assert_template "search/results"

     

    然后我们想要判断查询所得到的商品信息:

    products = assigns(:products)

    assert_not_nil products

    assert_equal 1, products.size

    assert_equal "Pragmatic Version Control", products[0].title

     

    我们还想判断用来显示查询结果的页面的一些内容,我们查询到的商品会作为列表在页面上显示,我们使用catelog视图相同的css样式:

    assert_tag :tag => "div",

          :attributes => { :class => "results" },

          :children => { :count => 1,

          :only => { :tag => "div",

          :attributes => { :class => "catalogentry" }}}

     

    下面是完整的测试方法:

    def test_search

        get :search, :title => "Pragmatic Version Control"

        assert_response :success

        assert_equal "Found 1 product(s).", flash[:notice]

        assert_template "search/results"

        products = assigns(:products)

        assert_not_nil products

        assert_equal 1, products.size

        assert_equal "Pragmatic Version Control", products[0].title

        assert_tag :tag => "div",

          :attributes => { :class => "results" },

          :children => { :count => 1,

          :only => { :tag => "div",

          :attributes => { :class => "catalogentry" }}}

      end 

     

    现在我们来运行测试:ruby test/functional/search_controller_test.rb

    不出意外,会得到下面的结果:

    test_search(SearchControllerTest) [test/functional/search_controller_test.rb:17]:

    <"Found 1 product(s)."> expected but was

    <nil>.

    1 tests, 2 assertions, 1 failures, 0 errors

     

    因为我们还没有设置flash的内容,进一步说,我们还没有实现search这个Action。怎样实现,书上给留了个作业。OK,那我们就自己来一步步实现searchAction

    1.       search方法添加内容:

    @products = Product.find(:all,:conditions=>['title=?',params[:title]])

        if not @products.nil?

          flash[:notice] = sprintf('Found %d product(s).',@products.size)

        end

       

        render(:action=>'results')现在运行测试,结果如下:

    ----------------------------------------------------------------------------

      1) Failure:

    test_search(SearchControllerTest)

        [Z:/study/ruby/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack……

         Z:/study/ruby/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack……

         test/functional/search_controller_test.rb:19:in `test_search']:

    expecting <"search/results"> but rendering with <"search/search">

    1 tests, 3 assertions, 1 failures, 0 errors

    ----------------------------------------------------------------------------

     

    2.       这次轮到assert_template "search/results"断言出错了,是因为我们还没有results这个View,我们在view目录下添加一个results.rhmtl文件,在search_controller.rb文件中添加一个results的空方法:

    def results                               

    end

    还要在search方法中添加一句:render("search/results"),然后再运行测试,结果如下:

    ----------------------------------------------------------------------------

    Finished in 0.125 seconds.

      1) Failure:

    test_search(SearchControllerTest)

        [Z:/study/ruby/InstantRails/ruby/lib/ruby/gems/1.8/gems/…… Z:/study/ruby/InstantRails/ruby/lib/ruby/gems/1.8/gems/……

    expected tag, but no tag found matching {:attributes=>{:class=>"results"}, :tag=>"div",

    "<h1>Search#results</h1>\n<p>Find me in app/views/search/results.rhtml</p>\n".

    <nil> is not true.

    ----------------------------------------------------------------------------

     

    3.       现在可以看到,就只有最后一个断言assert_tag没有通过了,这个断言是对页面上的元素进行判断的,所以我们来实现results页面。仔细看看断言的内容,我们就知道只要在results.rhtml里添加两个div就可以了,下面是results.rhtml的完整内容:

    <h1>Search#results</h1>

    <p>Find me in app/views/search/results.rhtml</p>

    <div class="results">

        <div class = "catalogentry">

        </div>

    </div>

    保存,然后再运行测试,激动人心的时刻来临了,所有的断言都通过了!测试OK了,下面是结果:

    ----------------------------------------------------------

    DEPRECATION WARNING: You called render('search/result……

    t Z:/study/ruby/InstantRails/ruby/lib/ruby/gems/1.8/g……

    Finished in 0.094 seconds.

    1 tests, 7 assertions, 0 failures, 0 errors

    ----------------------------------------------------------

    4.       在实现search.rhtmlresults.rhtml的时候,我碰到了一些问题,用测试用例都可以选出数据来,但是通过页面就怎么也不行了,把log里的sql贴出来到phpMyAdmin里执行,也能选出数据,真不知道是怎么回事,自己对rails的理解还不深,自己胡乱写了这些代码,先把代码都帖出来,等自己对rails有更深入的理解的时候看能不能找到问题。同时也请高人指点

    search_controller_test.rb:

    require File.dirname(__FILE__) + '/../test_helper'

    require 'search_controller'

     

    # Re-raise errors caught by the controller.

    class SearchController; def rescue_action(e) raise e end; end

     

    class SearchControllerTest < Test::Unit::TestCase

      fixtures :products

      def setup

        @controller = SearchController.new

        @request    = ActionController::TestRequest.new

        @response   = ActionController::TestResponse.new

      end

     

      def test_search

        get :search, :title => "Pragmatic Version Control"

        assert_response :success

        assert_equal "Found 1 product(s).", flash[:notice]

        assert_template "search/results"

        products = assigns(:products)

        assert_not_nil products

        assert_equal 1, products.size

        assert_equal "Pragmatic Version Control", products[0].title

        assert_tag :tag => "div",

          :attributes => { :class => "results" },

          :children => { :count => 1,

          :only => { :tag => "div",

          :attributes => { :class => "catalogentry" }}}

      end 

    end

     

    search_controller.rb

    class SearchController < ApplicationController

     

      def search

        print(params[:title])

        @products = Product.find(:all,:conditions=>['title=?',params[:title]])

       

        if not @products.nil?

          flash[:notice] = sprintf('Found %d product(s).',@products.size)

        end

        print(flash[:notice])

        #redirect_to(:action=>'results')

        render(:action=>'results')

      end

     

      def results

       

      end

      def index

       

      end

    end

     

    Views下有三个文件:index.rhtmlresults.rhtmlsearch.rhtml

    index.rhtml

    <html>

    <%= form_tag(:action=>'search',:id=>@products) %>

        <table>

                <tr>

                        <td>Book title:</td>

                        <td><%=text_field("title","")%></td>

                </tr>

               

                <tr>

                        <td><input type="submit" value="SEARCH" /></td>

                </tr>

        </table>

    <%= end_form_tag %>

    </html>

     

    results.rhtml

    <h1>Search#results</h1>

    <p>Find me in app/views/search/results.rhtml</p>

    <div class="results">

        <div class = "catalogentry">

                <table cellpadding="10" cellspacing="0">

                <tr class="carttitle">

                        <td >title</td>

                        <td >description</td>

                        <td >price</td>

                </tr>

               

                <%

                printf("result:%d",@products.size)

                for product in @products

                -%>

                        <tr>

                                <td><%= product.title %></td>

                                <td><%= product.description%></td>

                                <td align="right"><%= fmt_dollars(product.price) %></td>

                        </tr>

                <% end %>

     

        </table>

        </div>

    </div>

     

    search.rhtml

     <html></html>

  • 相关阅读:
    springboot文件上传: 单个文件上传 和 多个文件上传
    Eclipse:很不错的插件-devStyle,将你的eclipse变成idea风格
    springboot项目搭建:结构和入门程序
    POJ 3169 Layout 差分约束系统
    POJ 3723 Conscription 最小生成树
    POJ 3255 Roadblocks 次短路
    UVA 11367 Full Tank? 最短路
    UVA 10269 Adventure of Super Mario 最短路
    UVA 10603 Fill 最短路
    POJ 2431 Expedition 优先队列
  • 原文地址:https://www.cnblogs.com/dahuzizyd/p/ruby_rails_dotneter_study_27.html
Copyright © 2011-2022 走看看