等式 的 リファクタと回帰 テスト
関数型スタイルでは「この変形で意味は同じか」を小さく検証しながら進めるのが有効です。
ここでは 2 つの実装が同じ結果を返すことを、複数ケースで固定します。
実装を差し替えても挙動を維持する
TEST
#entry main
#indent 4
#target std
#import "core/math" as *
#import "core/result" as *
#import "std/test" as *
fn sum_to_loop <(i32)*>i32> (n):
let mut i <i32> 0
let mut acc <i32> 0
let n1 <i32> add n 1
while lt i n1:
do:
set acc add acc i
set i add i 1
acc
fn sum_to_formula <(i32)->i32> (n):
let n1 <i32> add n 1
let num <i32> mul n n1
div_s num 2
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>>:
checks_new
|> checks_push check_eq_i32 sum_to_loop 0 sum_to_formula 0
|> checks_push check_eq_i32 sum_to_loop 1 sum_to_formula 1
|> checks_push check_eq_i32 sum_to_loop 10 sum_to_formula 10
|> checks_push check_eq_i32 sum_to_loop 100 sum_to_formula 100
let shown <Vec<Result<(),str>>> checks_print_report checks;
checks_exit_code shown失敗ケースも同時に固定する
TEST
#entry main
#indent 4
#target std
#import "core/math" as *
#import "core/result" as *
#import "std/test" as *
fn safe_div_old <(i32,i32)->Result<i32,str>> (a, b):
if eq b 0 then Result::Err "division by zero" else Result::Ok div_s a b
fn safe_div_new <(i32,i32)->Result<i32,str>> (a, b):
if:
cond eq b 0
then Result::Err "division by zero"
else Result::Ok div_s a b
fn assert_same <(i32,i32)*>Result<(),str>> (a, b):
match safe_div_old a b:
Result::Ok ov:
match safe_div_new a b:
Result::Ok nv:
check_eq_i32 ov nv
Result::Err ne:
Result<(),str>::Err "old=Ok new=Err"
Result::Err oe:
match safe_div_new a b:
Result::Ok nv:
Result<(),str>::Err "old=Err new=Ok"
Result::Err ne:
Result<(),str>::Ok ()
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>>:
checks_new
|> checks_push assert_same 10 2
|> checks_push assert_same 11 3
|> checks_push assert_same 10 0
let shown <Vec<Result<(),str>>> checks_print_report checks;
checks_exit_code shown