继续把model
的测试写完
private方法
属於不直接测试,利用有用到它们的public
方法测试即可。类别方法与实体方法都应该要测试。
我新增了一些测试,假设都是我想增加的功能。
require 'rails_helper'
RSpec.describe Role, type: :model do
let!(:role) { create(:role) }
describe 'associations' do
end
describe "测试验证功能" do
end
describe "#attack_power" do
it "基本攻击力等於力量*10"
it "力量是6基本攻击力为60"
it "力量是4基本攻击力为40"
it "武器DPS是所持sword的dps"
it "min = 2 , max = 4 , dps = 3"
it "真正攻击力等基本攻击力*武器DPS"
it "力量4 武器min:2, max:5 真正攻击力120"
end
end
为了有纪录力量
、基本攻击力
、真正攻击力
与sword_dps
,在Role
加上这些些栏位。
Sword
我们一样假设测试过了。不良示范了
Role
$ rails g migration add_role_column_about_attack_power
class AddRoleColumnAboutAttackPower < ActiveRecord::Migration[6.1]
def change
add_column :roles, :power, :integer
add_column :roles, :attack_power, :integer
add_column :roles, :really_attack_power, :integer
add_column :roles, :sword_dps, :integer
end
end
$ rails db:migrate
#帅一点的指令。
$ rails g migration AddColumnsToRole power:integer attack_power:integer really_attack_power:integer sword_dps:integer
$ rails db:migrate
Sword
$ rails g migration add_column_sword_min_max_damge
class AddColumnSwordMinMaxDamge < ActiveRecord::Migration[6.1]
def change
add_column :swords, :min_damge, :integer
add_column :swords, :max_damge, :integer
end
end
$ rails db:migrate
Factory_bot
当然需要修改。
spec/factories/role
FactoryBot.define do
factory :role do
user
name { Faker::Name.first_name }
job { Faker::Job.title }
age { rand(5..130)}
power {5}
attack_power {nil}
really_attack_power {nil}
after :create do |role|
create_list :sword, 3, role: role #has_many这样建立,数字代表建立几个。
#create :sword, role: role ##has_one这样建立。
end
end
end
spec/factroies/sword
FactoryBot.define do
factory :sword do
role
min_damge { 3 }
max_damge { 6 }
end
end
都是简单计算,省略过程。
role.spec.rb
describe "#attack_power" do
it "基本攻击力等於力量*10" do
expect(role.attack_power).to be(role.power * 10)
end
it "力量是6基本攻击力为60" do
role.power = 6
expect(role.attack_power).to be(60)
end
it "力量是4基本攻击力为40" do
role.power = 4
expect(role.attack_power).to be(40)
end
it "武器DPS是所持sword的dps" do
expect(role.sword_dps).to be(role.swords.first.dps)
end
it "min = 2 , max = 4 , dps = 3" do
role.swords.first.min_damge = 2
role.swords.first.max_damge = 4
expect(role.sword_dps).to be(3)
end
it "真正攻击力等基本攻击力*武器DPS" do
expect(role.really_attack_power).to be(role.attack_power * role.sword_dps)
end
it "力量4 武器min:2, max:5 真正攻击力120" do
role.power = 4
role.swords.first.min_damge = 2
role.swords.first.max_damge = 5
expect(role.really_attack_power).to be 120
end
end
role.rb
class Role < ApplicationRecord
def attack_power
power * 10
end
def really_attack_power
attack_power * sword_dps
end
def sword_dps
@sword = self.swords.first
@sword.dps
end
end
sword.rb
class Sword < ApplicationRecord
#略...
def dps
(min_damge + min_damge) / 2
end
end
到这边rspec
也没有问题。
role.rb
的sword_dps
变成private
。role.rb
private
def sword_dps
@sword = swords.first
@sword.dps
end
end
rspec
画面会出现错误,都是跟private
有关的。
内容都是找不到sword_dps
这方法了。
.............FFF.
Failures:
NoMethodError:
private method sword_dps called for #<Role:0x00007f814d0161b8>
#略...
rspec ./spec/models/role_spec.rb:62 # Role#attack_power 武器DPS是所持sword的dps
rspec ./spec/models/role_spec.rb:66 # Role#attack_power min = 2 , max = 4 , dps = 3
rspec ./spec/models/role_spec.rb:72 # Role#attack_power 真正攻击力等基本攻击力*武器DPS
噗噗,就算再简单,花时间的测试,等於没测了。
很多人会这样说,私有方法不测试,应该更专注在你的公开方法上,因为要private
就代表不是要直接给使用者使用,或许因为商业逻辑很复杂,或许其他Model
也会一直用到这个方法,愿意的话测试也可以,但最终只会删除或变成无意义的注解,测试会变得没有意义,心里面安心而已。
真的要测可以利用send
方法处理(callback部分有示范),或是像我这样,测了再删。
可以看到我最後一个测试就是有调动到私有方法的,所以我可以安心的把这三个测试删除了(我在自己本机上是注解)。
这个部分并不是在分享该怎麽做
我也是Rspec
新手,但若确定自己要建立私有方法,照大家说的私有方法不测试,那代表我一开始测试的内容就不该那样设定。重点是怎麽规画好测试流程。
Callback的测试与私有方法很类似,就是测试有调动到Callback
的方法就好。
而部分会用到Callback
来执行的方法,可能都会成为private....
所以我今天的code
到最後可能只会剩下下面那样。
Role
before_update :attack_power, :really_attack_power
rspec/model/role_spec.rb
describe "#call_back before_update" do
it "素质更改後,攻击力会更改" do
create(
:role,
name: "测试用",
job: "战士",
age: "29",
power: "6",
attack_power: nil,
really_attack_power: nil
)
role.power = 5
role.save
expect(role.send(:attack_power)).to be(50)
expect(role.send(:really_attack_power)).to be(200)
end
end
在我本机上,我是没将这两个方法设私有,虽然只是简单的code
要直接删掉还真舍不得?
所以在设计时,就真的该想好哪些方法是private
方法。
今日的档案:https://github.com/nauosika/Rspec_test/tree/D14
Model
虽然是最简单的测试,但帮我自己纪录一下怎麽开头Rspec
。
关於分享测试就到今天结束了。
今天的leetcode.628:Maximum Product of Three Numbers
题目连结:https://leetcode.com/problems/maximum-product-of-three-numbers/
题目重点:考虑到负负得正,负负负会得负,正正负会得负,还有负数-1
最大-1000
最小。
#错的
def maximum_product(nums)
ans = 1
new_arr = nums.max(3)
new_arr.each do |num|
ans *= num
end
ans
end
这是我一开始的解法,没有考虑到值有超过三个时,两个很大的负数相乘再乘一个最大的正数,才会是正解。
submit
出去後发现还有一个例子。
[-100, -98, -1, 2, 3, 4]
但这个例子出现,其实也透露出答案了。
越小的负数,去掉负号後反而是最大的,以这个例子看就是前两个与最後一个相乘最大。last * nums[0] * nums[1]
,如果都是正数那一定是max(3).reduce(:*)
,那就这两个选大的。
不用去担心阵列中数字很多,数字越多,这种状况反而会越明显。
def maximum_product(nums)
nums.sort!
[nums.max(3).reduce(:*), nums.last * nums[0] * nums[1]].max
end
这样就解完了。
>>: Day 11 运算宝石:EC2 储存资源 EBS Types 方案比较
//装备药水:实现药水单向(若装备栏内没药水可直接装备)、双向置换(若装备栏内已经有药水,直接点击新...
接下来介绍比较运算值,也是用程序码跟注解来呈现 结果会以布林true跟false显示 ...
个人比较喜欢的流程是: 对方自我介绍、讲一下面试流程 让我自我介绍 ... 有些工程师可能很忙,面试...
经过昨天的介绍後,相信大家对App都有更一步的了解了,是吧!(应该有吧) 那我们今天就来做一点小小的...
透过前面 15 篇的文章,相信大家已经了解要怎麽利用 git 指令将档案进行版本控制、将档案 pus...