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:
-
test_function_<nb_args>_againt_solution: the usual. Test the student code against a given solution written in thesolution.mlfile. -
test_function_<nb_args>: compare the student code to a series of tests where both inputs and expected outputs are given. Note that you still need to write a solution insolution.mlto build your exercise session sincelearn-ocaml buildtests your grader withsolution.mlas the student copy.
A few words about grading function for functions
Grading functions for functions return a global report concatening 4 specific ones:
-
report resulting of comparison between student and solution outputs. The function
~testis used to build this report. By default,~testuses the structural equality to compare outputs. -
report resulting of comparison between student and solution standard outputs. The function
~test_stdoutis used to build this report. By default,~test_stdoutis set to ignore standard output and returns an empty report. -
report resulting of comparison between student and solution standard errors. The function
~test_stderris used to build this report. By default,~test_stderris set to ignore standard error and returns an empty report. -
report resulting of the result of function
~afterand returns an empty report by default.
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]:
-
ty: type of the tested function specified for the given tests. It must not contain type variables (i.e.'a,'betc..), match the type of the tests and be compatible with the solution. -
name: name of the tested function in the student code and insolution.ml -
tests: list of tested inputs.
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]:
-
ty: type of the tested function specified for the given tests. It must not contain type variables (i.e.'a,'betc..), match the type of the tests and be compatible with the solution. -
name: name of the tested function in the student code and insolution.ml -
(in, out, stderr, stdout) :: _astests: list of tuples where the first elementinis the argument passed to the tested function (for a three-arguments functionstestswill instead matched(in1, in2, in3, out, stderr, stdout)). The second elementoutis the expected output.stderrandstdoutare the expected strings in standard output and error output respectively.
Optional arguments of grading functions
-
gen: number of automatically generated tests. See step-3 and step-4 for more information. -
sampler: used to define sampler for automatically generating inputs for tests. See step-3 and step-4 for more information. -
test: is used to redefine the function which compare the output of the student function and the output of the solution. See WIP for more information. -
test_stdout: is used to redefine the function which compare the standard output channel of the student function and the one of the solution. See WIP for more information. -
test_stderr: is used to redefine the function which compare the standard error channel of the student function and the one of the solution. See WIP for more information. -
after: is used to redefine a function which is called with the current tested inputs, the student result and the solution result and returns a report. Enables for example to inspect references introduced with~before,~before_useror~before_referenceand build an appropriate report. See WIP for more information. -
before_reference: is used to redefine a function called right before the application of the current tested inputs to the solution. This enables for example to introduce a reference or make a side effect before each test. See WIP for more information. -
before_user: is used to redefine a function called right before the application the current tested inputs to the student function. This enables to introduce a reference or make a side effect between solution evaluation and student function evaluation. See WIP for more information. -
before: same asbefore_referencefortest_function_<nb_args>. Since no solution is evaluated, there is no need to distinguish between before or after solution evaluation.
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.