5-13 Rspec实际; validates处理Errors, TDD, 单元测试和验收测试,capybara


validates处理验证错误:详见ActiveModel::Errors文档 

一,errors

ActiveModel::Errors的实例包含所有的❌。每个错误:key是每个属性的name, value是一个数组,包含错误消息string. 

例子:

person = Person.new 

person.errors.messages   #=> {:name => ["can't be blank", "is too short"], ...}

 

二 ,errors[]

通过key获取value ,如person.errors[:name]  #=> ["can't be blank", "is too short"]

 

三, errors.add(atr, msg) 或者 errors.message[atr] << "msg"

手动添加某属性的错误message

errors.full_messages: 友好显示所有错误message, 用嵌套的hash显示。

 

add(attribute, message=:invalid, options={})

添加message给errors, 同时可以使用validator type 来在attribute上显示details  

同一个attributes可以同时添加多个error。

如果没有自定义message ,默认使用:invalid。

 

 > p.errors.add(:title, :not_implemente, message: "must be implemented")
 => ["must be implemented"]
 > p.errors.messages
 => {:title=>["must be implemented"]}
 > p.errors.details
 => {:title=>[{:error=>:not_implemente}]}

 

分析: :not_implemente是自定义的验证类型,对应其message。使用p.errors.details,得到的是属性和属性指向的错误类型,

 

 

四, errors.details,

在add()方法内增加限制参数,not_allowed: "xxx" 

 

五, errors[:base] << "string"

如果error不是直接管理到具体一个attribute上,可以使用:base . 

把错误message添加到整个对象上。不是针对属性。不管什么错误,只像把对象标记为无效,就使用这个方法。 

 

六,errors.clear 和 errors.empty?

清除errors 集合中所有message, errors.empty?查看是否错误集合是空的,配合clear使用。

 

七,errors.size,返回错误消息总数。 等同errors.count

 

八,视图上显示错误消息。

可以使用scarfold,在_form.html.erbzhong 自动加入ERB代码。或者自己写。

 

 


 

validate(*args, &block) #用于 自定义的验证方法  

validates(*attributes)  #用于验证表格的属性。这里有s

 


Rspec的方法:

to_not , be_valid 

 

 


 

Rails程序开发,时间区默认是UTC,需要改为"Beijing"

在config/application.rb中,类Application中,加config.time_zone = "Beijing" 


Float#ceil, 返回大于等于某个数字的最小的数字。参数指小数点后的位数。
1.2.ceil      #=> 2
2.0.ceil      #=> 2
(-1.2).ceil   #=> -1
(-2.0).ceil   #=> -2
1.234567.ceil(3)   #=> 1.235

 


 

TDD(Test-Driven Development)

测试驱动开发:

 

  1. 刚开始写测试的时候,关键要素,是测什么,要测试哪些案例example才算程序正确,可以列表一个清单。
  2. 先看到测试失败,才表示测试有作用。因此,可以先写测试代码,再写实做代码。
  3. 不要一次性把全部测试example写完,而是新写一段测试代码,让测试失败,再改正实做让实做通过,最后改进这个代码refactor重构。反复这个步骤,完成全部测试example。

 

 


测试代码比实做代码多是正常的,但很简单

 

  1. 建立测试资料
  2. 执行程序
  3. 检查结构-> TDD

 

 


 

如何在测试中除错 

1利用puts输出信息

 

2关注需要除错的example

 

  • 方法1: 把其他案例注释掉
  • 方法2:编辑spec/rails_helper.rb,加上两行设定

 

spec/rails_helper.rb
  RSpec.configure do |config|
  # (略)

+  config.filter_run :focus => true
+  config.run_all_when_everything_filtered = true

 

然后修改 spec/models/parking_spec.rb 针对你想要单独测试的案例it/或者一组案例context,加上 :focus => true,例子:

it "30 mins should be ¥2", :focus => true do...end

 

 

3.使用内置gem 'byebug'。 平时开发除错也可以使用。

app/models/parking.rb
   def calculate_amount 
+    byebug      # (略)

执行测试会在中途停顿,并告知上下文环境。输入最后输入 continue 就会继续执行下去

 


Float@truncate: 返回要求的位数,默认只返回整数。

%:整除。 

 


 


 

Feature Spec 验收测试

需要用到gem 'capybara' 水豚的意思。

Key benefits:

 

  • works out of the box for Rails。开箱即用
  • Intuitive API: mimics the language an actual user would use. 直观直觉API 

 

 

Setup:

gem 'capybara'  

 

Using Capybara with RSpec 

在spec/rails_helper.rb添加(或者其他test helper file):

require 'capybara/rails'

require 'capybara/rspec' 

⚠️: rails_helper已经require了文件spec_helper。所以require 'capybara/rspec'可以放到这两个文件任意一个中。

 

问题 :type => :feature 到底加不加,有啥用?

文档:

如果用Rails,并且Capybara specs文件在其他目录(非spec/features,or spec/system), 需给example groups加上tag, type: :feature or type: :system


 

问题:如果测试JavaScript。

 使用js:true 来打开Capybara.javascript_dirver(默认:selenium)(具体看文档说明,有点复杂)

describe 'some stuff which requires js', js: true do
  it 'will use the default js driver'
 # it 'will switch to one specific driver', driver: :webkit
end

 

 


执行 mkdir spec/features 建立验收测试的目录

新增 spec/features/guest_spec.rb

require 'rails_helper'
feature "parking", :type => :feature do
  scenario "guest parking" do
    visit "/"   #浏览首页

    save_and_open_page 

    expect(page).to have_content("一般费率") #检查HTML中应出现"一般费率"
    click_button "开始计费" #按键
    click_button "结束计费"
    expect(page).to have_content("2.00")
  end
end

 解释: 

  1. feature 是别名: describescenario (a written outline of what happens in a film/movie or play 剧情概要。)等同于 it
  2. 其他别名:background: before, given: let
  3. 这里 have_content 来检查指定文字有没有出现在 HTML 里面。Web 应用的测试,没办法去完整比对 HTML 字串,因为字串比对差一个空白就不一样。如果说设计师稍微多加一个 <br> 就要改测试,这样就太累了,测试会太敏感。所以我们只能检查说 HTML 里面有出现我们希望要有的关键字。
  4. 注意到我们不需要再重复测试金额对不对了。Feature Spec 的重点在于检查东西(Model + Controller + View)接起来有没有正常运作。
  5. 被注解掉的 save_and_open_page 会存下测试当时的 HTML 页面(snapshot网页块照),除错的时候可以使用。如果打开的话,跑测试会出现:
File saved to /Users/chentianwei/离线保存的全栈文件/我的练习/rails自动化测试/parking-app/ tmp/capybara/capybara-201805142036353571416628.html.



 

    within("#new_user") do  # 填表单,模拟用户填写表单送出的情况。
      fill_in "Email", with: "foobar@example.com"
      fill_in "Password", with: "12345678"
      fill_in "Password confirmation", with: "12345678"
    end
 
 
   click_button "Sign up"
  expect(page).to have_content("Welcome! You have signed up successfully")
这里我们模拟用户填写表单送出的情况,用 fill_in 可以填入值

 

测试短期费率流出 

Devise 提供测试用的 sign_in 方法,请改 spec/rails_helper.rb

spec/rails_helper.rb
  RSpec.configure do |config|  
+ +    config.include Devise::Test::ControllerHelpers, type: :controller 
+    config.include Devise::Test::ControllerHelpers, type: :view 
+    config.include Devise::Test::IntegrationHelpers, type: :feature 

spec/features/short_term_spec.rb
require "rails_helper"

feature "parking", :type => :feature do

  scenario "short-term parking" do
    user = User.create!(email: '1@1.com', password:'123123')
    sign_in(user)  #这样就直接登入了。

    visit '/'
    choose "短期费率" #选择radio button
    click_button "开始计费"
    click_button "结束计费"
    expect(page).to have_content("2.00")
  end
end

这里用了 choose 来对 Radio 按钮做选择,在 capybara 中还有提供其他方法针对不同表单元件做操作,例如:

  • check "核选方块名称"
  • uncheck "核选方块名称"
  • select "选项名称", :from => "下拉选单名称"
  • attach_file 上传档案

详细用法请参考 capybara 文件。

 

The DSL

A complete reference is available at rubydoc.info.

⚠️:默认的Capybara只会定位可见的元素,因为真实用户不会和不可见的元素互动。

 pasting


Navigating

 

vist方法,例子: 

visit "/projects" 

vist (post_comments_path(@post))

 

have_current_path方法:当前页面又这个路径

expect(page).to have_current_path(post_comments_path(post))

 

Clicking links and buttons

Full reference:  Capybara::Node::Actions

 

Capybara自动跟随redirect, submits forms 相关的buttons

click_link('Link Text')
click_button('Save')
click_on('Link Text') # clicks on either links or buttons

Interacting with forms

Full reference:  Capybara::Node::Actions

 

fill_in('First Name', with: 'John')
fill_in('Password', with: 'Seekrit')
fill_in('Description', with: 'Really Long Text...')
choose('A Radio Button')
check('A Checkbox')
uncheck('A Checkbox')
attach_file('Image', '/path/to/image.jpg')
select('Option', from: 'Select Box')

#fill_in([locator], options = {}) ⇒ Capybara::Node::Element

 

定位一个text field或text area, 并填写进string, 可以通过name, id, label text来定位到这个元素。

 

参数: 

locator(String)-- Which field  to fill in

options(Hash) (默认{}) 

选项:

:with(String):所要填入的值。

:id(String) -- 定位的选项。

:name(String)-- 定位的选项。

:class(String,Array<String>) -- 定位的选项。

 

Querying

Full reference: Capybara::Node::Matchers

一系列选项用来查询页面是否存在某个元素,操作这个元素。 

You can use these with RSpec's magic matchers:

expect(page).to have_selector('table tr') 
expect(page).to have_selector(:xpath, './/table/tr')  
expect(page).to have_xpath('.//table/tr') 
expect(page).to have_css('table tr.foo') 
expect(page).to have_content('foo')

 

 


 

Finding

Full reference: Capybara::Node::Finders

指定寻找元素,并操作。

find_field('First Name').value
find_field(id: 'my_field').value
find_link('Hello', :visible => :all).visible?
find_link(class: ['some_class', 'some_other_class'], :visible => :all).visible?

find_button('Send').click
find_button(value: '1234').click

find(:xpath, ".//table/tr").click
find("#overlay").find("h1").click
all('a').each { |a| a[:href] }
find('#navigation').click_link('Home')
expect(find('#navigation')).to have_button('Sign out')

Scoping

 

Restrict certain actions, such as interacting with forms or clicking links and buttons, to within a specific area of the page.  within method. 

within("li#employee") do
  fill_in 'Name', with: 'Jimmy'
end

Restrict: ~ sth: to limit the size, amount or range of sth.

within_fieldset(), within_table()也一样。 

 

Scripting

 在支持的drivers中,可以执行JavaScript, page.execute_script("$('body').empty()") 

 

Modals

In drivers which support it, you can accept, dismiss and respond to alerts, confirms and prompts.

accept_alert do
  click_link('Show Alert')
end


Debugging

网页快照snapshot存储当前页面在tmp/capybara/capybara-XXXxxx.html

save_and_open_page

You can also retrieve the current state of the DOM as a string using page.html.

print page.html		#在命令窗口显示html代码。

 


Asynchronous JavaScript (Ajax and friends)

当想要操作一个异步的JS, Capybara自动等待元素在这个页面出现。

可以调整时间,默认2秒。在时间内等待,超出则放弃或throw an error

Capybara.default_max_wait_time = 5

Capybara's waiting behaviour is quite advanced, and can deal with situations such as the following line of code:

expect(find('#sidebar').find('h1')).to have_content('Something')

 

转载于:https://www.cnblogs.com/chentianwei/p/9031423.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值