Ruby基本介绍(八)Rspec幼稚园等级实作

DDU-DU DDU-DU~

十几亿的观看次数...跟四十多亿次的某只MV还有一段距离XD


预防针:由於是菜鸟分享心得,以下测试内容,非常基础。

如果是初学神书内容部分觉得太难,再来看我的超级幼稚园等级的Rspec流程。

请确定已安装gem Rspec

$ gem install rspec

幼稚园等级规格书:产生一把新的剑,剑有最大最小攻击力。

请先建立model,file/sword.rb

class Sword
end

接着建立测试档案file/sword_spec.rb

require "./sword"  

RSpec.describe Sword do
  context "规格书大项" do
    it "拆分细节处理"
  end
end

把内容写入

require "./sword"

RSpec.describe Sword do
  context "产生一把新剑" do
    it "会有最小攻击力"
    it "会有最大攻击力"
  end
end

执行测试指令,应该会跑出下面画面

$ rspec sword_spec.rb         
**

Pending: (Failures listed here are expected and do not affect your suite's status)

  1) Sword 产生一把新剑 会有最小攻击力
     # Not yet implemented
     # ./sword_spec.rb:5

  2) Sword 产生一把新剑 会有最大攻击力
     # Not yet implemented
     # ./sword_spec.rb:6


Finished in 0.00251 seconds (files took 0.07607 seconds to load)
2 examples, 0 failures, 2 pending

如果没问题,我们继续对测试档案做修改

require "./sword"

RSpec.describe Sword do
  context "产生一把新剑" do
    it "会有最小攻击力" do
      @sword = Sword.new
      @sword.min_attack
    end
    it "会有最大攻击力" do
      @sword = Sword.new
      @sword.min_attack
    end
  end
end

执行测试後观察,错误内容应该都是没有方法。

  NoMethodError:
       undefined method `min_attack' for #<Sword:0x00007fe749a4b928>
       
  NoMethodError:
       undefined method `min_attack' for #<Sword:0x00007fe749a437f0>

那我们便制造方法。

#file/sword.rb
class Sword

  def initialize
    @sword = {min_attack: nil, max_attack: nil}
  end
  
  def min_attack
  end

  def max_attack
  end
  
end

跑测试会发现两个测试项目都绿灯了。
那我们增加一点点点规格书难度。

幼稚园等级规格书:产生一把新的剑,剑有最小攻击力,在1~3之间。会有最大攻击力在4~6之间。

require "./sword"

RSpec.describe Sword do
  context "产生一把新剑" do
    it "最小攻击力在1~3之间" do
      @sword = Sword.new
      @min_attack = @sword.min_attack
      expect(@min_attack).to match 1..3
    end
    it "最大攻击力在4~6之间" do
      @sword = Sword.new
      @max_attack = @sword.max_attack
      expect(@max_attack).to match 4..6
    end
  end
end

#to be, to match都是Rspec内有的语法,请自行查一下Rspec的说明书。

执行测试後,可以发现错误

  1) Sword 产生一把新剑 最小攻击力在1~3之间
     Failure/Error: expect(@sword.min_attack).to match 1..3
       expected nil to match 1..3
     # ./sword_spec.rb:8:in `block (3 levels) in <top (required)>'

  2) Sword 产生一把新剑 最大攻击力在4~6之间
     Failure/Error: expect(@sword.max_attack).to match 4..6
       expected nil to match 4..6
     # ./sword_spec.rb:13:in `block (3 levels) in <top (required)>'

因为我们没有让这两个方法(min,max_attack)有回传值,所以都出现nil to match,那我们就增加流程控制并回传正确值。

class Sword

  def initialize
    @sword = {min_attack: nil, max_attack: nil}
  end

  def min_attack
    @sword[:min_attack] = rand(1..3)
  end

  def max_attack
    @sword[:max_attack] = rand(4..6)
  end

end

虽然有语法上的漏洞,但是我们发现测试过了,先不理会漏洞,我们再加工一下测试档案

require "./sword"
RSpec.describe Sword do
  context "产生一把新剑" do
    it "最小攻击力在1~3之间" do
      @sword = Sword.new
      @min_attack = @sword.min_attack
      expect(@min_attack).to match 1..3
      p @sword
    end
    it "最大攻击力在4~6之间" do
      @sword = Sword.new
      @max_attack = @sword.max_attack
      expect(@max_attack).to match 4..6
      p @sword
    end
  end
end

#执行测试,并印出我们的实体。

可以发现@sword

#<Sword:0x00007fbb47b932a0 @sword={:min_attack=>2, :max_attack=>nil}>
#<Sword:0x00007fbb47b805b0 @sword={:min_attack=>nil, :max_attack=>5}>

不是一被new出来时,就有正确的数值在里面了,所以我们再改一下Sword.rb。

class Sword
  def initialize
    @sword = {min_attack: nil, max_attack: nil}
    self.min_attack
    self.max_attack
  end

  def min_attack
    @sword[:min_attack] = rand(1..3)
  end

  def max_attack
    @sword[:max_attack] = rand(4..6)
  end
end

再跑一次测试,可以发现new新的Sword时,实体已经确认建立完整。

当然实务上,可能没有人会去测试开发资料表,也可能都是建立DB後,去针对model及controller所需要的新功能去做TDD。

这整个测试很简陋。
那我们来直接为已经建立好的这个model再加一个小功能。

规格书:Sword需要一个新的功能,可以附魔,附魔之後最大攻击力随机+2~4,,但最大攻击力不可以超过10。
建立一个新的测试档案方便观察(可用前一个测试档)
直接完成後如下

require "./sword"
RSpec.describe Sword do
  context "附魔" do
    it "新剑可以操作附魔,最大攻击力+2~4,但最大攻击力不可以超过8" do
      @sword = Sword.new
      p @sword
      @sword.enchant
      expect(@sword.enchanted).to be <= 8
      p @sword.enchanted
      p @sword
    end
  end
end

sword.rb会多出

def enchant
  @sword[:max_attack] += rand(2..4)
  if @sword[:max_attack] > 8
    @sword[:max_attack] = 8
  end
end

def enchanted
  @sword[:max_attack]
end

可以发现物件在正个操作流程中,都会一直受到改变。

在rails上测试与在ruby上会有不同的地方,主要是因为框架建立了更多ruby本身没有的功能,所以在测试上感受会有所不同。

最後记得TDD是一种行为,要把这个行为变成一个技能...要很努力很努力。

超幼稚园等级TDD分享完成....又再骗字数了


<<:  Day33 参加职训(机器学习与资料分析工程师培训班),网站设计与网页工程技术

>>:  第35天~

Proxmox VE 安装容器:Rocky Linux 8.4 及其它应用 (WordPress, Nextcloud, Odoo)

前一章我们采用 Proxmox VE 所提供的现成范本档,方便快速的布建完成一部 Ubuntu 2...

强人PM与敏捷相遇 -1

大概在2018年的时候,开始认识敏捷。会想要认识敏捷,其实也是服务的公司碰到了一定程度的发展瓶颈。 ...

【Day26】反馈元件 - Progress bar

元件介绍 Progress bar 是能够展示当前进度的进度条元件。当一个操作需要显示目前百分比,或...

第42天~

这个得上一篇:https://ithelp.ithome.com.tw/articles/10258...

DAY 26 首页文章

终於跳脱 header 的部分来到了下面文章列表啦,总觉得光是上半部就做了好久,不知道完赛前能不能把...