王筝的博客
ruby学习

https://github.com/thoughtbot/shoulda-matchers

 

加了gem ‘shoulda-matchers’, ‘~> 3.0’,

报错是因为没有配置spec/rails_helper.rb,详细内容在上面连接里的configuration里

Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    # Choose a test framework:
    with.test_framework :rspec
    with.library :rails
  end 
end

 

推荐两个网址:

https://github.com/rspec/rspec-rails

http://rspec.info/documentation/

上传了一个api的单元测试,https://github.com/shiralwz/grape_api_rspec

主要步骤:

(1)在Gemfile里加入新gem

gem 'rspec-rails', '~> 3.0'

(2)Download and install by running

bundle install

(3)Initialize the spec/ directory (where specs will reside) with

rails generate rspec:install

运行这个命令会自动生成以下三个文件

  • .rspec
  • spec/spec_helper.rb
  • spec/rails_helper.rb

(4)新增单元测试的代码

(5)执行

bundle exec rspec  spec/...

============================

对api的单元测试代码

require 'rails_helper'

RSpec.describe "helloAPI",type: :request do
  describe "GET the /api/hello" do
    it 'should return correct response via GET' do
      get '/api/hello', name: 'Mike'
      expect(response).to be_success
      expect(response).to have_http_status(200)
      body = JSON.parse(response.body)
      body['message'] == 'Hello Mike via GET'
    end 
  end 

  describe "POST the /api/hello" do
    it 'should return correct response via POST' do
      post '/api/hello', name: 'Mike'
      expect(response).to be_success
      expect(response).to have_http_status(200) //这里由于在api里设置了200所以检测200,默认是201
      body = JSON.parse(response.body)
      body['message'] == 'Hello Mike via POST'
    end 
  end 
end

 

 

 

https://github.com/thoughtbot/shoulda-matchers

shoulda-matchers对应了可以测试Rails常规功能的方法,使得测试用例非常简洁高效,有了它,妈妈再也不担心我不会写单元测试了

shoulda-matchers provides Test::Unit- and RSpec-compatible one-liners that test common Rails functionality. These tests would otherwise be much longer, more complex, and error-prone.

如何安装使用?

(1)把下面的几行加到Gemfile文件里

group :test do
  gem 'shoulda-matchers', require: false 
end

其中require:false表示不自动加载

(2)修改spec_helper.rb,加上下面两行
require 'rspec/rails'
require 'shoulda/matchers'

ActiveModel Matchers

ActiveRecord Matchers

ActionController Matchers

# -*- encoding : utf-8 -*-
class CmsUser < ActiveRecord::Base
validates_presence_of :email
validates_uniqueness_of :email

def password=(password)
write_attribute :password, self.class.md5(password)
end

def self.authenticate(username, password)
CmsUser.where(username: username, password: md5(password)).first
end

def self.md5(str)
Digest::MD5.hexdigest(str.to_s)
end
end

———–

# -*- encoding : utf-8 -*-
require ‘spec_helper’
describe CmsUser do
describe “validations” do
it { should validate_presence_of(:email) }
it { should validate_uniqueness_of(:email) }

it “valid” do
user = build :cms_user
user.should be_valid
end
end

describe “set password” do
it “value will convert to md5″ do
user = build :cms_user
user.password = “password”
user.password.should eq Digest::MD5.hexdigest(“password”)
end
end

describe “authenticate with username and password” do
let!(:tester) { create :cms_user, username: “user”, password: “password” }

it “return user with valid user info” do
user = CmsUser.authenticate tester.username, “password”
user.id.should eq tester.id
end

it “return nil with invalid user info” do
user = CmsUser.authenticate tester.username, “wrong_password”
user.should be_nil
end
end
end

 

 

https://github.com/thoughtbot/factory_girl

https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md

http://ruby.taobao.org/

今天项目结束,打算搞一下接手这个项目之前的单元测试,因为接受的时候很多测试是跑不通的,于是重新学习了一下 factory_girl

gem install factory_girl (半天没响应)

由于国内网络原因(你懂的),导致 rubygems.org 存放在 Amazon S3 上面的资源文件间歇性连接失败。所以你会与遇到 gem install rack 或 bundle install 的时候半天没有响应,具体可以用 gem install rails -V 来查看执行过程。现在来更换一下gem source

$ gem sources --remove https://rubygems.org/
$ gem sources -a http://ruby.taobao.org/
$ gem sources -l
*** CURRENT SOURCES ***

http://ruby.taobao.org

# 请确保只有 ruby.taobao.org

Configure your test suite

# rspec
RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end

# Test::Unit
class Test::Unit::TestCase
  include FactoryGirl::Syntax::Methods
end

# Cucumber
World(FactoryGirl::Syntax::Methods)

# Spinach
class Spinach::FeatureSteps
  include FactoryGirl::Syntax::Methods
end

# MiniTest
class MiniTest::Unit::TestCase
  include FactoryGirl::Syntax::Methods
end

# MiniTest::Spec
class MiniTest::Spec
  include FactoryGirl::Syntax::Methods
end

# minitest-rails
class MiniTest::Rails::ActiveSupport::TestCase
  include FactoryGirl::Syntax::Methods
end

由于我们用的是rspec,所以选第一种,所在spec/spec_helper.rb里配置第18行那句

1 # -*- encoding : utf-8 -*-
2 # This file is copied to spec/ when you run ‘rails generate rspec:install’
3 ENV[“RAILS_ENV”] ||= ‘test’
4 require File.expand_path(“../../config/environment”, __FILE__)
5 require ‘rspec/rails’
6 require ‘rspec/autorun’
7 require “email_spec”
8
9 # Requires supporting ruby files with custom matchers and macros, etc,
10 # in spec/support/ and its subdirectories.
11 Dir[Rails.root.join(“spec/support/**/*.rb”)].each {|f| require f}
12 Dir[Rails.root.join(“lib/mock*.rb”)].each {|f| require f}
13
14 RSpec.configure do |config|
15 config.fixture_path = “#{::Rails.root}/spec/fixtures”
16 config.use_transactional_fixtures = true
17 config.infer_base_class_for_anonymous_controllers = false
18 config.include FactoryGirl::Syntax::Methods
19 config.global_fixtures = :all
20 config.include(EmailSpec::Helpers)
21 config.include(EmailSpec::Matchers)
22 end

 

Defining factories

# This will guess the User class
FactoryGirl.define do
  factory :user do
    first_name "John"
    last_name  "Doe"
    admin false
  end

  # This will use the User class (Admin would have been guessed)
  factory :admin, class: User do
    first_name "Admin"
    last_name  "User"
    admin      true
  end
end

一般在factories的文件夹,以modle名字来命名factory,这样更清晰

来看看我写的这段

FactoryGirl.define do
factory :cms_tv_version do
title “2.0.0”
state 1
end
end



 

 

今天有两个单元测试一直跑不通,究其原因是没搞清楚单元测试的传参的概念,之前大师强调过的,今天pp又讲解了一遍。以第一个单元测试的测试模块的25行为例

25 put :modify, :id => @list.id, :rankinglist => {:title => new_title}

这个报错是因为我写成了list =>{:title => new_title},但是被测模块里是没有这个参数的,想知道有啥就看被测模块 params里面的内容啊,有几个传几个就行。

这个巧合的是我的前端代码是这样的

<%=  text_field_tag  ‘title’ ,@rankinglist.title  %>由于text_field_tag里的内容在html里解析为id=‘title’,name =’title’,所以在25行里没有:title也是ok的

23def modify
24 @rankinglist.title = params[:title]
25 if @rankinglist.update_attributes(params[:rankinglist])
26 redirect_to edit_tv_i_rankinglist_path(:id => @rankinglist.id) , :notice => ‘操作成功’
27 else
28 render :action => “edit”
29 end
30 end

 

对应的单元测试

23it ‘should put update’ do
24 new_title = ‘test’
25 put :modify, :id => @list.id, :rankinglist => {:title => new_title}
26 @list.reload.title.should == new_title
27 end

 

再来看第二个写错的单元测试

5def index
6 @module_type = params[:module_type]
7 @rankinglists = CmsTvRankingList.where(‘state = ? ‘, 1)
8 @rankinglist = CmsTvRankingList.find_by_id(params[:rankinglist_id]) || @rankinglists.try(:first)
9 @modules = CmsTvRankingListModule.where(‘rankinglist_type = ? ‘, @rankinglist.id).order(:position)
10 end

对应的单元测试

5before do
6 admin_login
7 request.env[“HTTP_REFERER”] = root_path
8 @rankinglist = CmsTvRankingList.create(:title =>’5′ ,:state => ‘1’)
9 @module = CmsTvRankingListModule.create(:title => ‘测试’, :rankinglist_type => 5)
10 end
11 it ‘should get index’ do
12 get :index, :rankinglist_id =>’1′
13 response.should be_success
14 end

错在哪里呢,由于这个排行榜子菜单是在排行榜菜单内部的,所以是需要先保证被测的第8行是有值的,所以需要写上测试里的第8行,当然,测试的12行后半句也是必要的。