zoukankan      html  css  js  c++  java
  • Rails 5 Test Prescriptions 第11章其他部分的测试。

    • Routes✅
    • Helper Methods✅
    • Controllers and Requests✅
    • Simulating Requests⚠️,看之前的博客
    • What to Expect in a Request Spec ✅
    • Older Rails Controller Tests ❌
    • Testing Mailers ❌
    • Testing Views and View Markup✅
    • Using Presenters ❌没看需要额外gem
    • Testing Jobs and Cables
    这些测试有2方面的讨论:
    • 在集成测试中应测试什么,在单元测试中应测试什么
    • 什么代码应归入controller, view, mailer,job,or其他,什么应该被提取出来放入一个不同的对象? 
    Rails团队更喜欢集成测试,抛弃了控制器测试,它们的观点rails中额外的layers是不需要的。因为你想让代码保持Rails结构,就多用集成测试开发,少用单元测试开发。

    Testing Routes (官方不推荐)

    集成测试中也有visit , have_current_path .

    RSpec-Rails 把routing test 放入spec/routing 目录。

    rspec-rails中定义的匹配器route_to , be_routable

    例子:

    RSpec.describe "project routing", :aggregate_failures, type::routing do

      it "routes projects" do

        expect(get: "projects/new").to route_to(

           controller:"projects", action:"show", id:"1") 

        expect(delete: "/projects/1").to route_to(

          controller: "projects", action: "destroy", id: "1")

        expect( get: "/projects/search/fred").not_to  be_routable ,#路径不存在。

      end 

    end 


    Testing Helper Methods (不推荐使用)

    Helper modules 

    设计用于保存可反复用的视图逻辑。 视图指定的数据的存在,或者条件逻辑:关于内容显示。

    因为测试它们的有点tricky,一般不测试helper modules.

    目录: spec/helpers

    例子:

    对页面的project的显示状态schedule进行不同的设计。设计使用css,根据是否在计划表中使用不同的css进行装饰。因此会根据project的schedule相关属性来改变css.

    given: 一个project,和它的schedule属性

    when:调用helper方法name_with_status,返回一个<span>及对应的class。

    then: 判断返回的结过,是否是希望的selector. 

    RSpec.describe ProjectsHelper, type: :helper do
      let(:project) { Project.new(name: "Project Runway") }
      it "augments with status info when on schedule" do
        allow(project).to receive(:on_schedule?).and_return(true) 
        actual = helper.name_with_status(project)
        expect(actual).to have_selector("span.on_schedule", text: "Project Runway")
      end

     

      it "augments with status info when behind schedule" do
        allow(project).to receive(:on_schedule?).and_return(false)
        actual = name_with_status(project)
        expect(actual).to have_selector("span.behind_schedule", text:"Project Runway")
      end
    end
    然后运行出错,在app/helpers/projects_helper.rb文件中。
    module ProjectsHelper
      def name_with_status(project)
        if  project.on_schedule?
          dom_class = "on_schedule"
        else
          dom_class = "behind_schedule"
        end
        content_tag(:span, project.name, class: dom_class)
      end
    end
    再测试成功

    #helper是对象,删掉不影响测试。

    Block作为wrapper也是很有帮助的,它可以包含许多不同类型的text:

    例子:

    def if_logged_in

       yield if logged_in?

    end 

    对应的是:

    <% if_logged_in do%>

         <%= link_to "logout", logout_path %>

    <% end %> 

    对应的测试方法:

    it "displays if logged in" do
    login_as users( :quentin )
    expect(logged_in?).to be_truthy
    expect(if_logged_in {
    "logged in" }).to eq( "logged in" )

    end


    Testing Controllers and Requests (官方已遗弃)

    官方放弃了控制器测试的一些功能。

    本章看RSpec features in Rails 5,然后回顾控制器测试在之前的版本如何工作的。

    reason

    • 有经验的Rails coders ,新用rails5可能会用这些功能
    • 新手,你很可能会邂逅控制器测试,所以你想要看看它做什么。
    RSpec for Rails5有2种测试类型,设计用于测试单一的控制器行为,它们类似:
    • Request specs 是wrappers around集成测试
    • controller test 是 RSpec wrappers around Rails5 controller tests.

    Simulating Requests 

    models比requests更容易测试 ,容易提取,在一个测试框架内使用独立。

    需要用到HTTP verb

    What to Expect in a Request Spec 


    have_http_status (:success/:missing/:redirect/:error)

    :success 200–299

    :redirect 300–399

    :missing 404

    :error 500–599  

    参考博文: 

    https://www.cnblogs.com/chentianwei/p/9055336.html 

    https://www.cnblogs.com/chentianwei/p/9060522.html 


    Testing Mailers (没看)

    mailers功能还不是很了解。 


    Testing Views and View Markup 

    之前测试了一个project status的helper,但在浏览器这个新status DOM元素没有显示。因为模版view还没有改动。 此时:

    • 如果原则上没有逻辑的改变,或对大的架构无关紧要,并且很容易检查。就无需测试
    • 可以写个集成测试使用Capybara.如果你是out-in development,你已经在集成测试中写了测试。
    • 如果是个新加的功能,还有第三种办法,写一个Rails view test。比集成测试快。
    默认的约定目录: spec/views/projects/index.html.erb_spec.rb

     RSpec 允许视图测试独立于控制器。也不推荐在控制器测试中加入视图测试。

    视图测试文件加后缀_spec 和 视图文件一一对应。 

    作者说:

    很少写这类测试,因为文件结构很难维持一致(经常变化?)。作者在视图中建立的逻辑常常在集成测试和对象中测试。总的来说,完全的TDD-view很难,先写视图代码,再测试更容易。

    现在用第三个办法实做:

    require "rails_helper"
    describe "projects/index" do #会定位到app/views/projects/index_html.erb
      let(:on_schedule) { FactoryBot.build_stubbed(:project, 
      due_date: 1.year.from_now, name: "On Schedule") }
      let(:behind_schedule) { FactoryBot.build_stubbed(:project,
    due_date: 1.day.from_now, name: "Behind Schedule") }
      let(:completed_task) { FactoryBot.build_stubbed(:task, completed_at: 1.day.ago,

    project_id: on_schedule.id) }

      let(:incomplete_task) { FactoryBot.build_stubbed(:task,

    project_id:behind_schedule.id) }

      it "renders the index page with correct dom elements" do
        @projects = [on_schedule, behind_schedule]
        render

        #可以写完整的,如果是partial,就要写清楚了如:render partial:""

        expect(rendered).to have_selector(
          "#project_#{on_schedule.id} .on_schedule")
        expect(rendered).to have_selector(
          "#project_#{behind_schedule.id} .behind_schedule")
      end
    end

    测试❌,因为没改view 。

          <tr class="project-row" id="<%= dom_id(project) %>">
            <td class="name"> <%=  name_with_status(project)  %> </td>


    Testing Jobs and Cables 


     先看一下指导。

    Active Job Basics(假设开发者不是新人了。我还没有看懂,需要实例,案例及相关讲解)

    说明创建,入队和执行后台作业的基础知识。 

    1.介绍 

    Jobs是一个框架,声明jobs并让它们在各种队列后端运行。这些jobs可以是任意事情,从定期规范的清理,到账单收费,到发邮件。任何事情都能被分成多个小单位的工作并平行运行。

    2.目的

    确保Rails apps将有一个工作基础设施。我们然后把框架特点和其他gems建立在它的上面。 无需担心不同jobs运行程序(Resque/Delayed)的API之间的差异。

    3.创建 Jobs

     bin/rails generate job guests_cleanup
     invoke  test_unit
     create    test/jobs/guests_cleanup_job_test.rb
     create  app/jobs/guests_cleanup_job.rb
    
    class GuestsCleanupJob < ApplicationJob

    queue_as :default

      def perform(*args)

    # Do sth later

    end 

    end 

    4 Enqueue the job 作业入队

    #入队一个作业,作业在队列系统空闲的时候就立刻执行。 

    GuestsCleanupJob.perform_later guest

    #入队一个作业,设定在明天的中午执行。 

    GuestsCleanupJob.set(wait_until: Date.tomorrow.noon).perform_later(guest)

    #set(options={})具体见API,创建一个job并预制一些设置参数。可以和perform_later连用。

    wait: 1.week

    wait_until:

    queue:指定作业在哪个队列中运行。


    #'perform_later'"perform_now" 会在幕后调用perform 

    GuestsCleanupJob.perform_later(guest1,guest2, filter:"some_filter") 

    5. 执行jobs 

    生产环境中的多数应用应该挑选一个持久后端,即第三方队列库。

    5.1backend后端

    Active Job 为多种队列后端(Sidekiq、8000+星)内置了适配器。

    5.2设置后端

    在config/application.rb中设置,或者在各个作业中配置后端也行。

     http://guides.rubyonrails.org/active_job_basics.html

    5.3 启动后端

    看Sidekiq相关配置:

      https://github.com/mperham/sidekiq/wiki/Active+Job

    6 queue队列 

    可以把作业调动到具体的队列中。
    class PublishToFeedJob < ActiveJob::Base
      queue_as :feeds
    
      def perform(post)
        post.to_feed!
      end
    end
    7callback回调

    钩子。

    class GuestsCleanupJob < ApplicationJob
      queue_as :default
     
      around_perform :around_cleanup
     
      def perform
        # Do something later
      end
     
      private
        def around_cleanup(job)
          # Do something before perform
          yield
          # Do something after perform
        end
    end

    8 Action Mailer 常见的作业是在请求-响应循环之外发生邮件,无需用户等待。Active Job和Mailer是

    集成的。使用deliver_now/deliver_later

    9-11 国际化异步发送邮件;处理异常 


    Testing Jobs and Cables

    大概讲了一下。没有案例。Cable没有支持单元测试 





  • 相关阅读:
    Jquery操作表单Select元素常用方法
    NBear视频教程下载
    JSDT jQuery 自动完成功能设置
    JQuery插件收藏
    IE 性能分析工具
    Zend Studio for Eclipse 6.1与Spket整合进行Extjs开发
    英语中最常见的一百个词根
    MFC对话框背景色的设置
    防止屏幕闪烁
    MFC定时器
  • 原文地址:https://www.cnblogs.com/chentianwei/p/9123322.html
Copyright © 2011-2022 走看看