NEPLg2 Tutorial - 14 - 等式的リファクタと回帰テスト
Web Playground
Web Playground

等式とうしきてきリファクタと回帰かいきテスト

関数型スタイルでは「この変形で意味は同じか」を小さく検証しながら進めるのが有効です。
ここでは 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