/// 744: Unit Test Organisation โ modules, helpers, AAA pattern
// โโ Code under test โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
pub fn clamp(lo: i32, hi: i32, x: i32) -> i32 {
x.max(lo).min(hi)
}
pub fn divide_checked(a: i64, b: i64) -> Option<i64> {
if b == 0 { None } else { Some(a / b) }
}
pub fn is_palindrome(s: &str) -> bool {
let bytes = s.as_bytes();
let n = bytes.len();
(0..n / 2).all(|i| bytes[i] == bytes[n - 1 - i])
}
pub fn fizzbuzz(n: u32) -> String {
match (n % 3, n % 5) {
(0, 0) => "FizzBuzz".into(),
(0, _) => "Fizz".into(),
(_, 0) => "Buzz".into(),
_ => n.to_string(),
}
}
// โโ Test helpers โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
#[cfg(test)]
mod helpers {
/// Assert that two f64 values are equal within epsilon.
pub fn assert_approx_eq(a: f64, b: f64, eps: f64) {
assert!((a - b).abs() < eps,
"assert_approx_eq failed: |{} - {}| = {} >= {}",
a, b, (a - b).abs(), eps);
}
/// Assert that a slice is sorted ascending.
pub fn assert_sorted<T: Ord + std::fmt::Debug>(v: &[T]) {
for w in v.windows(2) {
assert!(w[0] <= w[1], "not sorted: {:?}", v);
}
}
}
// โโ Unit tests โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
#[cfg(test)]
mod tests {
use super::*;
use helpers::*;
// โโ clamp โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
#[test]
fn test_clamp_when_below_lo_returns_lo() {
// Arrange
let (lo, hi, x) = (0, 10, -5);
// Act
let result = clamp(lo, hi, x);
// Assert
assert_eq!(result, 0);
}
#[test]
fn test_clamp_when_within_range_returns_x() {
assert_eq!(clamp(0, 10, 5), 5);
}
#[test]
fn test_clamp_when_above_hi_returns_hi() {
assert_eq!(clamp(0, 10, 15), 10);
}
#[test]
fn test_clamp_at_boundaries() {
assert_eq!(clamp(0, 10, 0), 0);
assert_eq!(clamp(0, 10, 10), 10);
}
// โโ divide_checked โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
#[test]
fn test_divide_checked_non_zero_returns_some() {
assert_eq!(divide_checked(10, 3), Some(3));
}
#[test]
fn test_divide_checked_by_zero_returns_none() {
assert_eq!(divide_checked(42, 0), None);
}
#[test]
fn test_divide_checked_negative_dividend() {
assert_eq!(divide_checked(-10, 2), Some(-5));
}
// โโ is_palindrome โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
#[test]
fn test_palindrome_empty_is_palindrome() {
assert!(is_palindrome(""));
}
#[test]
fn test_palindrome_single_char_is_palindrome() {
assert!(is_palindrome("a"));
}
#[test]
fn test_palindrome_racecar_is_palindrome() {
assert!(is_palindrome("racecar"));
}
#[test]
fn test_palindrome_hello_is_not_palindrome() {
assert!(!is_palindrome("hello"));
}
// โโ fizzbuzz โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
#[test]
fn test_fizzbuzz_divisible_by_both_returns_fizzbuzz() {
assert_eq!(fizzbuzz(15), "FizzBuzz");
}
#[test]
fn test_fizzbuzz_divisible_by_3_returns_fizz() {
assert_eq!(fizzbuzz(9), "Fizz");
}
#[test]
fn test_fizzbuzz_divisible_by_5_returns_buzz() {
assert_eq!(fizzbuzz(10), "Buzz");
}
#[test]
fn test_fizzbuzz_other_returns_number() {
assert_eq!(fizzbuzz(7), "7");
}
// โโ helpers โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
#[test]
fn test_assert_approx_eq_passes() {
assert_approx_eq(0.1 + 0.2, 0.3, 1e-10);
}
#[test]
fn test_assert_sorted_passes() {
assert_sorted(&[1, 2, 3, 4, 5]);
assert_sorted(&[1u8]);
assert_sorted::<i32>(&[]);
}
// โโ should_panic example โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
#[test]
#[should_panic]
fn test_integer_division_by_zero_panics() {
let zero = std::hint::black_box(0u32);
let _ = 5u32 / zero;
}
}
(* 744: Unit Test Patterns โ OCaml with Alcotest-style structure *)
(* The code under test *)
let clamp lo hi x = max lo (min hi x)
let divide_checked a b =
if b = 0 then None
else Some (a / b)
let is_palindrome s =
let n = String.length s in
let rec check i =
if i >= n / 2 then true
else if s.[i] <> s.[n - 1 - i] then false
else check (i + 1)
in
check 0
(* Helper assertion functions *)
let assert_some result =
match result with
| Some x -> x
| None -> failwith "Expected Some, got None"
let assert_none result =
match result with
| None -> ()
| Some _ -> failwith "Expected None, got Some"
(* AAA pattern tests *)
let test_clamp_below_lo () =
(* Arrange *)
let lo, hi, x = 0, 10, -5 in
(* Act *)
let result = clamp lo hi x in
(* Assert *)
assert (result = 0)
let test_clamp_within_range () =
let lo, hi, x = 0, 10, 5 in
let result = clamp lo hi x in
assert (result = 5)
let test_clamp_above_hi () =
let lo, hi, x = 0, 10, 15 in
let result = clamp lo hi x in
assert (result = 10)
let test_divide_checked_non_zero () =
let result = divide_checked 10 3 in
let v = assert_some result in
assert (v = 3)
let test_divide_checked_by_zero () =
assert_none (divide_checked 10 0)
let test_palindrome () =
assert (is_palindrome "racecar");
assert (is_palindrome "");
assert (is_palindrome "a");
assert (not (is_palindrome "hello"))
let () =
test_clamp_below_lo ();
test_clamp_within_range ();
test_clamp_above_hi ();
test_divide_checked_non_zero ();
test_divide_checked_by_zero ();
test_palindrome ();
Printf.printf "All OCaml tests passed!\n"