羅馬數字 Kata 測試練習

本章使用羅馬數字 Kata 來練習 RSpec。首先介紹一下羅馬數字系統。

羅馬人是聰明的一群人。他們征服了大部分的歐洲,統治長達數百年之久。他們發明了水泥和直路,甚至比基尼也是羅馬人發明的呢。但羅馬人所想出來的數字系統沿用時至今日

羅馬人使用英文字母來書寫數字 — I、V、X、L、C、D、M(注意這些字母有很多直線,容易在石板上刻出來)。

小於 3999 的數在羅馬數字系統使用七位數來書寫,以下是羅馬數字與十進位數字對應表(超過 3999 的數字有特別規則,這裡忽略)。

羅馬數字 十進位
M 1000
D 500
C 100
L 50
X 10
V 5
I 1

我們將寫一個羅馬數字轉換器,可以將我們使用的十進位數字跟羅馬數字互轉。

練習一:十進位轉羅馬

撰寫並測試一個叫做 decimal_to_roman 的方法,給入小於 3999 的正整數,回傳對應的羅馬數字。比如給入 1999 回傳 "MCMXCIX" 字串,用 RSpec 確認輸入輸出正確的語法如下:

expect(decimal_to_roman(1999)).to eq "MCMXCIX"
expect(decimal_to_roman(1987)).to eq "MCMLXXXVII"
expect(decimal_to_roman(339)).to  eq "CCCXXXIX"

練習二:羅馬轉十進位

撰寫並測試一個叫做 roman_to_decimal 的方法,給入合法的羅馬數字,回傳對應的正整數。比如給入 "MCMXCIX" 字串回傳 1999,用 RSpec 確認輸入輸出正確的語法如下:

expect(roman_to_decimal("MCMXCIX")).to    eq 1999
expect(roman_to_decimal("MCMLXXXVII")).to eq 1987
expect(roman_to_decimal("CCCXXXIX")).to   eq 339

參考資料:

前置作業

建立資料夾:

$ mkdir roman_numeral_kata
$ cd roman_numeral_kata

初始化 Bundler 來管理 dependencies:

$ bundle init

將這行加入 Gemfile 並安裝 RSpec:

gem "rspec"

然後執行:

$ bundle install

設定 RSpec:

$ rspec init
  create   .rspec
  create   spec/spec_helper.rb

新增羅馬數字轉換器檔案:

$ touch converter.rb

填入以下內容:

class Converter
  def decimal_to_roman(decimal)
  end
end

新增測試:

$ touch spec/converter_spec.rb

填入以下內容:

require_relative "../converter"

RSpec.describe Converter do
  let(:converter) { Converter.new }

  def decimal_to_roman(decimal)
    converter.decimal_to_roman(decimal)
  end

  describe "#decimal_to_roman" do
    it { expect(decimal_to_roman(1)).to eq "I"   }
    it { expect(decimal_to_roman(2)).to eq "II"  }
    it { expect(decimal_to_roman(3)).to eq "III" }
  end
end

輸入 $ rspec 看看應該有 3 個失敗的測試:

$ rspec
FFF

Failures:

  1) Converter#decimal_to_roman should eq "I"
     Failure/Error: it { expect(decimal_to_roman(1)).to eq "I"   }

       expected: "I"
            got: nil

       (compared using ==)
     # ./spec/converter_spec.rb:11:in `block (3 levels) in <top (required)>'

  2) Converter#decimal_to_roman should eq "II"
     Failure/Error: it { expect(decimal_to_roman(2)).to eq "II"  }

       expected: "II"
            got: nil

       (compared using ==)
     # ./spec/converter_spec.rb:12:in `block (3 levels) in <top (required)>'

  3) Converter#decimal_to_roman should eq "III"
     Failure/Error: it { expect(decimal_to_roman(3)).to eq "III" }

       expected: "III"
            got: nil

       (compared using ==)
     # ./spec/converter_spec.rb:13:in `block (3 levels) in <top (required)>'

Finished in 0.01363 seconds (files took 0.08355 seconds to load)
3 examples, 3 failures

Failed examples:

rspec ./spec/converter_spec.rb:11 # Converter#decimal_to_roman should eq "I"
rspec ./spec/converter_spec.rb:12 # Converter#decimal_to_roman should eq "II"
rspec ./spec/converter_spec.rb:13 # Converter#decimal_to_roman should eq "III"

如有任何問題請參考:https://github.com/JuanitoFatas/roman_numeral_kata/commit/304c17f51b82d5ac9dc87ef094f95e9ced9bf8d6

提示與解答

提示:試著以最少的程式碼,修復現有的測試,再加入新的具有代表性的測試,如此反覆,直到數字 1-3999 都可以正確轉換。

十進位轉羅馬解答請參考:https://github.com/JuanitoFatas/roman_numeral_kata/pull/1

寫出十進位轉羅馬以後,反過來一樣,先撰寫失敗的測試,補上需要的程式碼,修復測試,加入測試,如此反覆。

羅馬轉十進位解答請參考:https://github.com/JuanitoFatas/roman_numeral_kata/pull/2

其它

Sandi Metz 關於 Roman Numeral 的文章:http://www.sandimetz.com/blog/2016/6/9/make-everything-the-same

results matching ""

    No results matching ""