Custom Comparators#

By default all tests will assume that we want to test numbers. Often we might want to test more complex data types. For this you can define a custom comparator function.

Anatomy of a comparator#

A comparator has two arguments, student_answer and expected_answer and returns a tuple of (absolute_error, relative_error).

Here is a custom comparator for testing sets:

def compare_sets(student_answer, expected_answer):
    common_elements = expected_answer.intersection(student_answer)

    rel_error = len(common_elements) / len(expected_answer)
    abs_error1 = abs(len(common_elements) - len(expected_answer))
    abs_error2 = abs(len(common_elements) - len(student_answer))


    return max(abs_error1, abs_error2), rel_error

Example 1 - Variable Test with custom comparator#

Here is an example of how we can use this comparator in a VariableTest:

Student answer:

my_set = set([1, 2, 3, 4])

Test:

from e2xgradingtools import VariableTest, grade_report

tester = VariableTest(
    namespace=globals(),
    a_tol=0
)

percentage_passed = tester.test([
    dict(
        name="my_set",
        expected=set([1, 2, 3, 4, 5]),
        expected_type=set,
        comparator=compare_sets
    )
])

grade_report(percentage_passed, points=10)

Output:

============================================================
Variable Test

------------------------------------------------------------
Test for variable my_set failed
Expected {1, 2, 3, 4, 5}
Got {1, 2, 3, 4}
rel_error = 8.0000e-01, abs_error = 1.0000e+00
------------------------------------------------------------

============================================================
0 / 1 tests passed!
============================================================
### BEGIN GRADE
0.0
### END GRADE

Example 2 - Function Test with custom comparator#

Here is an example of how we can use this comparator in a FunctionTest:

def create_even_set(my_list):
    return set(my_list)
from e2xgradingtools import FunctionTest, grade_report

def create_even_set_ref(my_list):
    return set([elem for elem in my_list if elem % 2 == 0])

tester = FunctionTest(
    namespace=globals(),
    function_name="create_even_set",
    reference_function=create_even_set_ref,
    comparator=compare_sets
)

percentage_passed = tester.test([
    dict(
        arg=[2, 4]
    ),
    dict(
        arg=[1, 2, 3, 4]
    )
])

grade_report(percentage_passed, 10)

Output:

============================================================
Test for function create_even_set

------------------------------------------------------------
Test case {'arg': [1, 2, 3, 4]} failed!
Expected:
{2, 4}
Got:
{1, 2, 3, 4}
rel_error = 1.0000e+00, abs_error = 2.0000e+00

============================================================
1 / 2 tests passed!
============================================================
### BEGIN GRADE
5.0
### END GRADE