了解如何在 Exercism 上測試你的 Arturo 練習
Arturo 軌道使用 Unitt 3.0.0 單元測試套件來執行所有練習的測試。
這個套件提供了一個測試框架,同時支援現代的 RSpec 風格語法與舊版的 XUnit 風格語法。
在你本機的練習資料夾中執行arturo tester.art或exercism test,第一次執行時會從網際網路安裝這個套件。
或者,你也可以執行arturo --package install unitt 3.0.0來安裝 Unitt。
只有第一個測試會被執行並回報結果給你。
一旦那個測試通過,就取消跳過下一個測試並再次執行測試,直到每個測試都通過為止。
無論是 RSpec 還是 XUnit 的設定,做法都很簡單,只要分別從it.skip或test.skip中移除.skip就好。
所有測試都通過後,就可以提交你的解答,但要注意測試執行器會執行所有測試,包括被跳過的測試。
你下載的練習資料夾裡會有一些檔案,但以下是三個最關鍵的檔案。
leap/
├── src/leap.art # Your solution file
├── tests/test-leap.art # Test cases for the exercise
└── tester.art # Test runner entry point
執行arturo tester.art會設定好 Unitt,然後執行tests/test-leap.art裡的測試。
這些測試會匯入包含你解答的src/leap.art,然後針對你的解答在特定輸入下應該回傳什麼,做出一連串斷言。
isLeap?: function [year][
panic "please implement the isLeap? function"
]
開始一個練習時,你的解答檔案會附帶一個範本,裡面包含預期內容的基本結構。
在這個取自Leap的例子中,檔案裡有一個預期isLeap?函式的簡略定義,還有一個會停止測試執行的panic。
移除panic那一行,然後開始撰寫isLeap?的實作。
import.version:3.0.0 {unitt}!
import {src/leap}!
describe "Leap" [
it "a year not divisible by 4 is a common year" [
expects.be:'false? @[isLeap? 2015]
]
it.skip "a year divisible by 4 and not divisible by 100 is a leap year" [
expects.be:'true? @[isLeap? 1996]
]
]
describe定義了一組驗證共同事物的測試案例。這些都可以巢狀。it和it.skip都定義了單一測試案例,分別會被執行或跳過。expects帶出測試案例核心的斷言。expects.be接受一個述詞函式,用來做出斷言。在expects.be:'false? @[isLeap? 2015]中,測試套件正在斷言isLeap?函式在年份 2015 時應該回傳false。
另一種寫法是expects.be:'equal? @[false isLeapYear? 2015],我們在此斷言isLeapYear? 2015的回傳值等於false。
這種比較兩個值的較長形式,是 Arturo 軌道上最常見的斷言類型。
預期值在區塊中一定會排在結果值前面。
suite "Leap" [
test "a year not divisible by 4 is a common year" [
result: isLeap? 2015
assert -> false = result
]
test.skip "a year divisible by 4 and not divisible by 100 is a leap year" [
result: isLeap? 1996
assert -> true = result
]
]
Unitt v1 中推出的類 XUnit API 是為了向下相容而支援,它與現代的類 RSpec API 大致相同,差別只在於它的斷言較不靈活。
suite定義了一組驗證共同事物的測試案例。這些都可以巢狀。test和test.skip都定義了單一測試案例,分別會被執行或跳過。assert帶出測試案例核心的斷言。後面->右側的運算式必須是 true。使用 XUnit 測試時,通常會在assert那一行之前建立代表結果的變數,以及選擇性的預期值變數。
無論你使用的是 RSpec 還是 XUnit API,測試輸出都會大致相似。
唯一的差別在於每個測試名稱底下印出的內容。
XUnit 會使用求值後的值來回報斷言,所以你會看到false = false。
不過,RSpec 會回報成false? false,因為我們搭配expects使用了false?函式。
從頭說起,如果起始檔案中的panic沒有被移除,Arturo 會回報錯誤,而且不會執行任何測試。
Uncaught error in tests/test-leap.art:
#[
output: {
══╡ Program Error ╞═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ <script> ══
Please implement the isLeap? function
}
code: 1
]
一旦panic被取代,Arturo 就會回報測試中每個斷言的狀態。
現在第一個測試通過了,但第二個測試被跳過。
======== .unitt/tests/test-leap.art ========
Describe: Leap
✅ - assert that a year not divisible by 4 is a common year
✅: false? false
⏩ - assert that a year divisible by 4 and not divisible by 100 is a leap year
skipped!
========== Summary ==========
⏏️ TOTAL: 2 assertions
✅ PASSED: 1 assertion
⏩ SKIPPED: 1 assertion
❌ FAILED: 0 assertion
========== ======= ==========
在第二個測試被手動取消跳過之後,兩個測試都會被執行。
不過,目前的 isLeap? 程式碼實作只會回傳false,所以第二個測試的斷言失敗。
======== .unitt/tests/test-leap.art ========
Describe: Leap
✅ - assert that a year not divisible by 4 is a common year
✅: false? false
❌ - assert that a year divisible by 4 and not divisible by 100 is a leap year
❌: true? false
========== Summary ==========
⏏️ TOTAL: 2 assertions
✅ PASSED: 1 assertion
⏩ SKIPPED: 0 assertion
❌ FAILED: 1 assertion
========== ======= ==========
當你取消跳過更多測試時,這個過程會持續下去。 一旦所有測試都通過,你就完成了這個練習,可以提交解答。 請注意,測試執行器會執行所有測試,無論它們在本機是否被跳過。