Errors and testing
Error handling#
Faber tách biệt ba ý liên quan mà nhiều ngôn ngữ gộp vào cùng một dạng:
| Cấu trúc | Ý nghĩa |
|---|---|
→ T | Kênh trả về thành công thông thường |
T ∪ nihil | Sự vắng mặt trong miền giá trị thành công |
⇥ E | Kênh thoát thay thế có thể phục hồi dành cho lỗi |
Trả về thông thường#
hàm porta(số x) → số {
nếu x ≺ 0 do_đó trả 0
trả x * 2
}Hàm có thể thất bại#
Dùng ⇥ khi một hàm có thể thoát qua kênh lỗi:
hàm divide(số a, số b) → số ⇥ văn_bản {
nếu b ≡ 0 {
ném "division by zero"
}
trả a / b
}Ném — iace#
iace gửi một giá trị qua kênh lỗi:
hàm exigePositivum(số value) → trống ⇥ văn_bản {
nếu value ≺ 0 {
ném "negative value"
}
}Phục hồi — fac / cape#
Bên gọi phục hồi cục bộ bằng khối làm và trình xử lý bắt:
hàm divide(số a, số b) → số {
nếu b ≡ 0 do_đó trả 0
trả a / b
}
hàm tutum(số a, số b) → số {
làm {
trả divide(a, b)
}
bắt err {
cảnh_báo err
trả 0
}
}Một lời gọi hàm có thể thất bại trực tiếp không phải là một biểu thức thông thường. Đặt lời gọi đến các hàm → T ⇥ E bên trong một ranh giới làm / bắt đang hoạt động.
Phục hồi chuyển đổi nội tuyến#
⇥ cũng có thể chỉ định một giá trị phục hồi nội tuyến trên các phép chuyển đổi ↦:
hằng văn_bản raw ← "42"
hằng số n ← raw ↦ số ⇥ 0Hàm có thể thất bại chỉ tạo hiệu ứng#
Đối với các hàm có lỗi nhưng không trả về giá trị thành công, hãy bỏ qua → T:
hàm exigePositivum(số value) → trống ⇥ văn_bản {
nếu value ≺ 0 {
ném "negative value"
}
}Trạng thái hiện tại#
→, trả, ⇥, iace và làm / bắt là các bề mặt ngữ pháp và trình kiểm tra đang hoạt động. Việc hạ cấp cho Rust và Go đối với toàn bộ hành vi thời gian chạy của ⇥ / iace / bắt vẫn còn thiếu ở phần backend — các cấu trúc này vượt qua bước kiểm tra kiểu, nhưng hiện chưa phát sinh mã thời gian chạy có thể thất bại cho tất cả các đích.
Inline testing#
Faber có một framework kiểm thử hạng nhất được tích hợp sẵn trong ngôn ngữ, với ba từ khóa: probandum khai báo một nhóm kiểm thử, proba khai báo một ca kiểm thử đơn lẻ, và adfirma khẳng định một điều kiện. Các bài kiểm thử nằm trong cùng tệp với mã mà chúng kiểm thử, được chạy bằng faber test, và sử dụng cùng pipeline biên dịch như mã sản phẩm — nhận biết locale, kiểm tra kiểu, và hỗ trợ nhiều đích.
Ba từ khóa#
| Từ khóa | Vai trò | Tương đương gần đúng |
|---|---|---|
probandum | Khai báo một nhóm kiểm thử có tên | describe, #[cfg(test)] mod |
proba | Khai báo một ca kiểm thử đơn lẻ | it, #[test] |
adfirma | Khẳng định một điều kiện tại thời điểm chạy | assert!, assert_eq! |
probandum — nhóm kiểm thử#
Một khối probandum nhóm các ca kiểm thử có liên quan. Các nhóm có thể lồng nhau để tổ chức kiểm thử theo cấp bậc:
kiểm_thử "unum plus unum" {
khẳng_định 1 + 1 ≡ 2
}
kiểm_thử "multiplicatio" {
khẳng_định 3 * 4 ≡ 12
}
kiểm_thử "comparatio" {
hằng số x ← 10
khẳng_định x ≥ 10
}proba — ca kiểm thử#
Một khối proba chứa logic kiểm thử. Khối này có thể sử dụng mọi mã Faber —
liên kết biến, lời gọi hàm, luồng điều khiển — và kết thúc bằng một hoặc nhiều
khẳng định adfirma. Có thể gắn thẻ cho các bài kiểm thử bằng một marker tag
tùy chọn để chạy có chọn lọc:
proba "echo formats operands with one space" tag "coreutils" {
adfirma echo_textus(["hello", "world"]) ≡ "hello world"
}adfirma — khẳng định#
adfirma đánh giá một biểu thức boolean và báo lỗi nếu biểu thức đó sai.
Một chuỗi thông báo tùy chọn cung cấp ngữ cảnh khi xảy ra lỗi:
bắt_đầu {
hằng số x ← 10
# Simple assertion
khẳng_định x ≻ 0
# With custom message
khẳng_định x ≡ 10 secus "x decem esse debet"
# Multiple assertions in sequence
hằng văn_bản nomen ← "Marcus"
khẳng_định nomen ≡ "Marcus"
khẳng_định nomen ≠ "" secus "nomen vacuum non sit"
}Quy trình#
Các bài kiểm thử được chạy thông qua lệnh faber test:
faber test # run all tests in the current package
faber test examples/coreutils/packages/echo # run tests for a specific packageVì các bài kiểm thử nằm cạnh mã nguồn trong cùng tệp .fab, nên không có cấu trúc
thư mục kiểm thử riêng, không cần khai báo module kiểm thử, và cũng không có sự
khác biệt trong script build giữa bản build kiểm thử và bản build sản phẩm. Trình
biên dịch nhận biết khối nào là mã kiểm thử và khối nào là mã sản phẩm dựa trên
các từ khóa được sử dụng — probandum và proba được phân tích cú pháp nhưng
được loại khỏi các bản build sản phẩm.
Ví dụ thực tế#
Gói coreutils echo minh họa framework kiểm thử trong thực tế.
Các bài kiểm thử nằm trong cùng tệp với phần triển khai, bao phủ việc phân tích
tùy chọn, mở rộng escape và các trường hợp biên:
probandum "echo formatting" tag "coreutils" {
proba "empty operands format as empty text" {
fixum lista<textus> words ← vacua
adfirma echo_textus(words) ≡ ""
}
proba "single operand is unchanged" {
adfirma echo_textus(["hello"]) ≡ "hello"
}
proba "-E is a leading no-op option" {
adfirma echo_textus(["-E", "hello", "world"]) ≡ "hello world"
}
proba "-n suppresses the trailing newline flag" {
adfirma echo_novam_lineam(["-n", "hello"]) ≡ falsum
}
proba "-e expands the declared escape subset" {
adfirma echo_textus(["-e", "a\\nb"]) ≡ "a\nb"
adfirma echo_textus(["-e", "a\\tb"]) ≡ "a\tb"
}
}Ghi chú thiết kế#
Một số lựa chọn thiết kế làm framework kiểm thử của Faber khác với các phương pháp thông thường:
- Không có binary kiểm thử riêng. Bài kiểm thử là các khai báo trong cùng tệp nguồn, không phải một đích biên dịch riêng. Trình biên dịch lọc các khối kiểm thử khỏi đầu ra sản phẩm.
- Dùng thẻ, không dùng thư mục. Bài kiểm thử được tổ chức bằng các marker
tagthay vì cấu trúc thư mục. Một bài kiểm thử có thể thuộc nhiều trục tổ chức mà không cần di chuyển. - Đầy đủ pipeline biên dịch. Bài kiểm thử được kiểm tra kiểu, phân tích và nhận biết locale — cùng cờ
--reader-localecũng áp dụng cho đầu ra kiểm thử. - Nhiều đích. Bài kiểm thử chạy qua backend mà gói nhắm tới — bộ bước MIR cho
faber test --interpret, Rust đã biên dịch chofaber test. - Nhóm lồng nhau. Các khối
probandumcó thể lồng nhau, phản ánh cấu trúc của mã mà chúng kiểm thử.
Tham khảo#
examples/corpus/probandum/— các tệp ví dụprobandumexamples/corpus/proba/— các tệp ví dụprobaexamples/corpus/adfirma/— các tệp ví dụadfirmaexamples/coreutils/packages/echo/src/main.fab— cách sử dụng thực tế với các thẻ