learn-ocaml

Step 5: More about grading functions for functions

Warning This step is ahead of the current version of [learn-ocaml].

Different grading functions for functions

There are 2 main grading functions:

A few words about grading function for functions

Grading functions for functions return a global report concatening 4 specific ones:

test_function_<nb_args>_against_solution

Signature for unary function

val test_function_1_against_solution :
  ?gen: int ->
  ?test: 'b tester ->
  ?test_stdout: io_tester ->
  ?test_stderr: io_tester ->
  ?before_reference : ('a -> unit) ->
  ?before_user : ('a -> unit) ->
  ?after : ('a -> ('b * string * string) -> ('b * string * string) -> Learnocaml_report.report) ->
  ?sampler : (unit -> 'a) ->
  ('a -> 'b) Ty.ty -> string -> 'a list -> Learnocaml_report.item

Mandatory arguments [test_function_1_againt_solution_1 ty name tests]:

test_function_<nb_args>

Signature of grading function for unary function

val test_function_1 :
  ?test: 'b tester ->
  ?test_stdout: io_tester ->
  ?test_stderr: io_tester ->
  ?before : ('a -> unit) ->
  ?after : ('a -> ('b * string * string) -> ('b * string * string) -> Learnocaml_report.report) ->
  ('a -> 'b) Ty.ty -> string -> ('a * 'b * string * string) list -> Learnocaml_report.item

Mandatory arguments [test_function_1 ty name tests]:

Optional arguments of grading functions

Examples

Note: only trivial examples can be found here. For more advanced examples, see the corresponding tutorials.

Identity

This is a classical example of an unary function, with a user-defined sampler.

let exercise_1 =
  test_function_1_against_solution
  [%ty: int -> int]
  "identity"
  ~gen:10
  ~sampler:(fun () -> Random.int 42)
  [0 ; 42]

With test_function_1:

let exercise_2 =
  test_function_1
    [%ty: int -> int]
    "identity"
    [0, 0, "", "" ;
    42, 42, "", ""]  (* List of tests *)

Note that since the default comparison function for standard output and error actually ignore them, we could put anything as expected outputs in the tests list.

Hello world

Hello world is also very classical, however grading this function is a little more tricky since by default standard output and error output are ignored (meaning the student standard/error output can be different from the solution ones without causing a failure).

let exercise_2 =
  test_function_1_against_solution
    [%ty: unit -> unit]
    ~test:test_ignore
    ~test_stdout:io_test_equals
    "hello"
    ~gen:0
    [()]
let exercise_4 =
  test_function_1
  [%ty: unit -> unit]
  ~test:test_ignore
  ~test_stdout:io_test_equals
  "hello"
  [(), (), "Hello world!", ""]

The function test_ignore for optional argument test enables to ignore the student and solution output. On the contrary, io_test_equals for test_stdout enables to compare standard outputs with the structural equality.