羅馬數字 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
參考資料:
- http://codingdojo.org/cgi-bin/index.pl?KataRomanNumerals
- https://inst.eecs.berkeley.edu/~selfpace/studyguide/3S.rdngs/roman.nums.case.pdf
前置作業
建立資料夾:
$ 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。