def test_random_func(): """Tests the RandomFunction class""" center = 15 amplitude = 2 rf = RandomFunction(center=center, amplitude=amplitude) func = rf.gen_sample() for i in range(20): x = random.uniform(-10, 10) assert func(x) == func(x) assert center - amplitude <= func(x) <= center + amplitude assert not np.iscomplex(func(x)) rf = RandomFunction(center=center, amplitude=amplitude, complex=True) func = rf.gen_sample() for i in range(20): x = random.uniform(-10, 10) assert func(x) == func(x) assert np.iscomplex(func(x)) with raises(Exception, match="Expected 2 arguments, but received 1"): RandomFunction(input_dim=2).gen_sample()(1) with raises(Exception, match="Expected 1 arguments, but received 2"): RandomFunction(input_dim=1).gen_sample()(1, 2)
def test_docs(): """Make sure that the documentation examples work""" # Generate random real numbers between 3 and 7 sampler = RealInterval(start=3, stop=7) # This is equivalent to sampler = RealInterval([3, 7]) # The default is [1, 5] sampler = RealInterval() # Generate random integers between 3 and 7 inclusive sampler = IntegerRange(start=3, stop=7) # This is equivalent to sampler = IntegerRange([3, 7]) # The default is [1, 5] sampler = IntegerRange() # Select random numbers from (1, 3, 5, 7, 9) sampler = DiscreteSet((1, 3, 5, 7, 9)) # Always select 3.5 sampler = DiscreteSet(3.5) # Select random complex numbers from 0 to 1 + i sampler = ComplexRectangle(re=[0, 1], im=[0, 1]) # The default is re=[1, 3], im=[1, 3] sampler = ComplexRectangle() # Select random complex numbers from inside the unit circle sampler = ComplexSector(modulus=[0, 1], argument=[-np.pi, np.pi]) # The default is modulus=[1, 3], argument=[0, pi/2] sampler = ComplexSector() # Test dependent sampling sampler = DependentSampler(depends=["x", "y", "z"], formula="sqrt(x^2+y^2+z^2)") # Select either sin or cos randomly functionsampler = SpecificFunctions([np.cos, np.sin]) # Always select a single lambda function functionsampler = SpecificFunctions(lambda x: x * x) # Generate a random function functionsampler = RandomFunction(center=1, amplitude=2) # The default is center=0, amplitude=10 functionsampler = RandomFunction() # Generate a random sinusoid functionsampler = RandomFunction(num_terms=1) # Generate a function that takes in two values and outputs a 3D vector functionsampler = RandomFunction(input_dim=2, output_dim=3)
def test_overriding_functions(): grader = FormulaGrader(answers='z^2', variables=['z'], user_functions={ 're': RandomFunction(), 'im': RandomFunction() }, sample_from={'z': ComplexRectangle()}) learner_input = 're(z)^2 - im(z)^2 + 2*i*re(z)*im(z)' assert not grader(None, learner_input)['ok'] grader = FormulaGrader(answers='tan(1)', user_functions={'sin': lambda x: x}) assert grader(None, 'tan(1)')['ok'] assert not grader(None, 'sin(1)/cos(1)')['ok']
def test_ng_config(): """Test that the NumericalGrader config bars unwanted entries""" expect = "not a valid value for dictionary value @ data\['failable_evals'\]. Got 1" with raises(Error, match=expect): NumericalGrader(answers="1", failable_evals=1) expect = "not a valid value for dictionary value @ data\['samples'\]. Got 2" with raises(Error, match=expect): NumericalGrader(answers="1", samples=2) expect = "not a valid value for dictionary value @ data\['variables'\]. Got \['x'\]" with raises(Error, match=expect): NumericalGrader(answers="1", variables=["x"]) expect = "not a valid value for dictionary value @ data\['sample_from'\]. " + \ "Got {'x': RealInterval\({'start': 1, 'stop': 5}\)}" with raises(Error, match=expect): NumericalGrader(answers="1", sample_from={"x": RealInterval()}) expect = "not a valid value for dictionary value @ data\['user_functions'\]\['f'\]. " + \ "Got RandomFunction" with raises(Error, match=expect): NumericalGrader(answers="1", user_functions={"f": RandomFunction()}) expect = "not a valid value for dictionary value @ data\['user_functions'\]\['f'\]. " + \ "Got \[<ufunc 'sin'>, <ufunc 'cos'>\]" with raises(Error, match=expect): NumericalGrader(answers="1", user_functions={"f": [np.sin, np.cos]})
def test_fg_function_sampling(): """Test random functions in FormulaGrader""" grader = FormulaGrader(answers="hello(x)", variables=['x'], user_functions={'hello': RandomFunction()}) assert grader(None, 'hello(x)')['ok'] assert isinstance(grader.random_funcs['hello'], RandomFunction) grader = FormulaGrader(answers="hello(x)", variables=['x'], user_functions={'hello': [lambda x: x * x]}) assert isinstance(grader.random_funcs['hello'], SpecificFunctions) assert grader(None, 'hello(x)')['ok'] grader = FormulaGrader(answers="hello(x)", variables=['x'], user_functions={'hello': [np.sin, np.cos, np.tan]}) assert isinstance(grader.random_funcs['hello'], SpecificFunctions) assert grader(None, 'hello(x)')['ok'] grader = FormulaGrader( answers="hello(x)", variables=['x'], user_functions={'hello': SpecificFunctions([np.sin, np.cos, np.tan])}) assert isinstance(grader.random_funcs['hello'], SpecificFunctions) assert grader(None, 'hello(x)')['ok']
def test_ng_config(): """Test that the NumericalGrader config bars unwanted entries""" expect = r"not a valid value for dictionary value @ data\[u?'failable_evals'\]. Got 1" with raises(Error, match=expect): NumericalGrader(answers="1", failable_evals=1) expect = r"not a valid value for dictionary value @ data\[u?'samples'\]. Got 2" with raises(Error, match=expect): NumericalGrader(answers="1", samples=2) expect = (r"length of value must be at most 0 for dictionary value " r"@ data\[u?'variables'\]. Got \[u?'x'\]") with raises(Error, match=expect): NumericalGrader(answers="1", variables=["x"]) expect = ( r"extra keys not allowed @ data\[u?'sample_from'\]\[u?'x'\]. Got " r"RealInterval\({u?'start': 1, u?'stop': 5}\)") with raises(Error, match=expect): NumericalGrader(answers="1", sample_from={"x": RealInterval()}) expect = ( r"not a valid value for dictionary value @ data\[u?'user_functions'\]\[u?'f'\]. " r"Got RandomFunction") with raises(Error, match=expect): NumericalGrader(answers="1", user_functions={"f": RandomFunction()}) expect = (r"not a valid value for dictionary value @ data\[u?'user_functions'\]\[u?'f'\]. " + \ r"Got \[<ufunc 'sin'>, <ufunc 'cos'>\]") with raises(Error, match=expect): NumericalGrader(answers="1", user_functions={"f": [np.sin, np.cos]})
def test_argument_number_of_RandomFunction(): """Tests to make sure we can extract the number of inputs expected for a random function""" func = RandomFunction(input_dim=3).gen_sample() assert validatorfuncs.get_number_of_args(func) == 3
def test_docs(): """Test that the documentation examples work as expected""" grader = FormulaGrader(answers='1+x^2+y', variables=['x', 'y']) assert grader(None, '1+x^2+y')['ok'] grader = FormulaGrader(answers='1+x^2+y+z/2', variables=['x', 'y', 'z'], sample_from={ 'x': ComplexRectangle(), 'y': [2, 6], 'z': (1, 3, 4, 8) }) assert grader(None, '1+x^2+y+z/2')['ok'] grader = FormulaGrader(answers='a_{0} + a_{1}*x + 1/2*a_{2}*x^2', variables=['x'], numbered_vars=['a'], sample_from={ 'x': [-5, 5], 'a': [-10, 10] }) assert grader(None, 'a_{0} + a_{1}*x + 1/2*a_{2}*x^2')['ok'] grader = FormulaGrader(answers='1+x^2', variables=['x'], samples=10) assert grader(None, '1+x^2')['ok'] grader = FormulaGrader(answers='1+x^2', variables=['x'], samples=10, failable_evals=1) assert grader(None, '1+x^2')['ok'] grader = FormulaGrader(answers='abs(z)^2', variables=['z'], sample_from={'z': ComplexRectangle()}) assert grader(None, 'abs(z)^2')['ok'] grader = FormulaGrader(answers='sqrt(1 - cos(x)^2)', variables=['x'], sample_from={'x': [0, np.pi]}, blacklist=['sin']) assert grader(None, 'sqrt(1 - cos(x)^2)')['ok'] grader = FormulaGrader(answers='sin(x)/cos(x)', variables=['x'], whitelist=['sin', 'cos']) assert grader(None, 'sin(x)/cos(x)')['ok'] grader = FormulaGrader(answers='pi/2-x', variables=['x'], whitelist=[None]) assert grader(None, 'pi/2-x')['ok'] grader = FormulaGrader(answers='2*sin(theta)*cos(theta)', variables=['theta'], required_functions=['sin', 'cos']) assert grader(None, '2*sin(theta)*cos(theta)')['ok'] grader = FormulaGrader(answers='x*x', variables=['x'], user_functions={'f': lambda x: x * x}) assert grader(None, 'x^2')['ok'] grader = FormulaGrader(answers="f''(x)", variables=['x'], user_functions={"f''": lambda x: x * x}) assert grader(None, "f''(x)")['ok'] grader = FormulaGrader(answers="x^2", variables=['x'], user_functions={"sin": lambda x: x * x}, suppress_warnings=True) assert grader(None, 'sin(x)')['ok'] grader = FormulaGrader(answers="f(x)", variables=['x'], user_functions={"f": [np.sin, np.cos]}) assert grader(None, 'f(x)')['ok'] grader = FormulaGrader(answers="f''(x) + omega^2*f(x)", variables=['x', 'omega'], user_functions={ "f": RandomFunction(), "f''": RandomFunction() }) assert grader(None, "f''(x)+omega^2*f(x)")['ok'] grader = FormulaGrader(answers='1/sqrt(1-v^2/c^2)', variables=['v'], user_constants={'c': 3e8}) assert grader(None, '1/sqrt(1-v^2/c^2)')['ok'] grader = FormulaGrader( answers='2*sin(theta)*cos(theta)', variables=['theta'], forbidden_strings=[ '*theta', 'theta*', 'theta/', '+theta', 'theta+', '-theta', 'theta-' ], forbidden_message= "Your answer should only use trigonometric functions acting on theta, not multiples of theta" ) assert grader(None, '2*sin(theta)*cos(theta)')['ok'] grader = FormulaGrader(answers='2*sin(theta)*cos(theta)', variables=['theta'], tolerance=0.00001) assert grader(None, '2*sin(theta)*cos(theta)')['ok'] grader = FormulaGrader(answers='2*m', variables=['m'], metric_suffixes=True) assert grader(None, '2*m')['ok'] assert not grader(None, '2m')['ok'] def is_coterminal(comparer_params_evals, student_eval, utils): answer = comparer_params_evals[0] reduced = student_eval % (360) return utils.within_tolerance(answer, reduced) grader = FormulaGrader(answers={ 'comparer': is_coterminal, 'comparer_params': ['b^2/a'], }, variables=['a', 'b'], tolerance='1%') assert grader(None, 'b^2/a')['ok'] assert grader(None, 'b^2/a + 720')['ok'] assert not grader(None, 'b^2/a + 225')['ok']
def test_fg_debug_log(): set_seed(0) grader = FormulaGrader(answers='x^2 + f(y) + z', variables=['x', 'y', 'z'], sample_from={'z': ComplexRectangle()}, blacklist=['sin', 'cos', 'tan'], user_functions={ 'f': RandomFunction(), 'square': lambda x: x**2 }, samples=2, debug=True) result = grader(None, 'z + x*x + f(y)') message = ( "<pre>MITx Grading Library Version {version}<br/>\n" "Student Response:<br/>\n" "z + x*x + f(y)<br/>\n" "<br/>\n" "==============================================================<br/>\n" "FormulaGrader Debug Info<br/>\n" "==============================================================<br/>\n" "Functions available during evaluation and allowed in answer:<br/>\n" "{{ 'abs': <function absolute at 0x...>,<br/>\n" " 'arccos': <function arccos at 0x...>,<br/>\n" " 'arccosh': <function arccosh at 0x...>,<br/>\n" " 'arccot': <function arccot at 0x...>,<br/>\n" " 'arccoth': <function arccoth at 0x...>,<br/>\n" " 'arccsc': <function arccsc at 0x...>,<br/>\n" " 'arccsch': <function arccsch at 0x...>,<br/>\n" " 'arcsec': <function arcsec at 0x...>,<br/>\n" " 'arcsech': <function arcsech at 0x...>,<br/>\n" " 'arcsin': <function arcsin at 0x...>,<br/>\n" " 'arcsinh': <function arcsinh at 0x...>,<br/>\n" " 'arctan': <function arctan at 0x...>,<br/>\n" " 'arctan2': <function arctan2 at 0x...>,<br/>\n" " 'arctanh': <function arctanh at 0x...>,<br/>\n" " 'conj': <ufunc 'conjugate'>,<br/>\n" " 'cosh': <function cosh at 0x...>,<br/>\n" " 'cot': <function cot at 0x...>,<br/>\n" " 'coth': <function coth at 0x...>,<br/>\n" " 'csc': <function csc at 0x...>,<br/>\n" " 'csch': <function csch at 0x...>,<br/>\n" " 'exp': <function exp at 0x...>,<br/>\n" " 'f': <function f at 0x...>,<br/>\n" " 'fact': <function factorial at 0x...>,<br/>\n" " 'factorial': <function factorial at 0x...>,<br/>\n" " 'im': <function imag at 0x...>,<br/>\n" " 'kronecker': <function kronecker at 0x...>,<br/>\n" " 'ln': <function log at 0x...>,<br/>\n" " 'log10': <function log10 at 0x...>,<br/>\n" " 'log2': <function log2 at 0x...>,<br/>\n" " 're': <function real at 0x...>,<br/>\n" " 'sec': <function sec at 0x...>,<br/>\n" " 'sech': <function sech at 0x...>,<br/>\n" " 'sinh': <function sinh at 0x...>,<br/>\n" " 'sqrt': <function sqrt at 0x...>,<br/>\n" " 'square': <function <lambda> at 0x...>,<br/>\n" " 'tanh': <function tanh at 0x...>}}<br/>\n" "Functions available during evaluation and disallowed in answer:<br/>\n" "{{ 'cos': <function cos at 0x...>,<br/>\n" " 'sin': <function sin at 0x...>,<br/>\n" " 'tan': <function tan at 0x...>}}<br/>\n" "<br/>\n" "<br/>\n" "==========================================<br/>\n" "Evaluation Data for Sample Number 1 of 2<br/>\n" "==========================================<br/>\n" "Variables:<br/>\n" "{{ 'e': 2.718281828459045,<br/>\n" " 'i': 1j,<br/>\n" " 'j': 1j,<br/>\n" " 'pi': 3.141592653589793,<br/>\n" " 'x': 3.195254015709299,<br/>\n" " 'y': 3.860757465489678,<br/>\n" " 'z': (2.205526752143288+2.0897663659937935j)}}<br/>\n" "Student Eval: (14.7111745179+2.08976636599j)<br/>\n" "Compare to: [(14.711174517877566+2.0897663659937935j)]<br/>\n" "Comparer Function: <function equality_comparer at 0x...><br/>\n" "Comparison Result: {{ 'grade_decimal': 1.0, 'msg': '', 'ok': True}}<br/>\n" "<br/>\n" "<br/>\n" "==========================================<br/>\n" "Evaluation Data for Sample Number 2 of 2<br/>\n" "==========================================<br/>\n" "Variables:<br/>\n" "{{ 'e': 2.718281828459045,<br/>\n" " 'i': 1j,<br/>\n" " 'j': 1j,<br/>\n" " 'pi': 3.141592653589793,<br/>\n" " 'x': 2.694619197355619,<br/>\n" " 'y': 3.5835764522666245,<br/>\n" " 'z': (1.875174422525385+2.7835460015641598j)}}<br/>\n" "Student Eval: (11.9397106851+2.78354600156j)<br/>\n" "Compare to: [(11.93971068506166+2.7835460015641598j)]<br/>\n" "Comparer Function: <function equality_comparer at 0x...><br/>\n" "Comparison Result: {{ 'grade_decimal': 1.0, 'msg': '', 'ok': True}}<br/>\n" "</pre>").format(version=VERSION) assert result['msg'] == message
def test_docs(): """Test that the documentation examples work as expected""" grader = FormulaGrader(answers='1+x^2+y', variables=['x', 'y']) assert grader(None, '1+x^2+y')['ok'] grader = FormulaGrader(answers='1+x^2+y+z/2', variables=['x', 'y', 'z'], sample_from={ 'x': ComplexRectangle(), 'y': [2, 6], 'z': (1, 3, 4, 8) }) assert grader(None, '1+x^2+y+z/2')['ok'] grader = FormulaGrader(answers='1+x^2', variables=['x'], samples=10) assert grader(None, '1+x^2')['ok'] grader = FormulaGrader(answers='1+x^2', variables=['x'], samples=10, failable_evals=1) assert grader(None, '1+x^2')['ok'] grader = FormulaGrader(answers='abs(z)^2', variables=['z'], sample_from={'z': ComplexRectangle()}) assert grader(None, 'abs(z)^2')['ok'] grader = FormulaGrader(answers='sqrt(1 - cos(x)^2)', variables=['x'], sample_from={'x': [0, np.pi]}, blacklist=['sin']) assert grader(None, 'sqrt(1 - cos(x)^2)')['ok'] grader = FormulaGrader(answers='sin(x)/cos(x)', variables=['x'], whitelist=['sin', 'cos']) assert grader(None, 'sin(x)/cos(x)')['ok'] grader = FormulaGrader(answers='pi/2-x', variables=['x'], whitelist=[None]) assert grader(None, 'pi/2-x')['ok'] grader = FormulaGrader(answers='2*sin(theta)*cos(theta)', variables=['theta'], required_functions=['sin', 'cos']) assert grader(None, '2*sin(theta)*cos(theta)')['ok'] grader = FormulaGrader(answers='x*x', variables=['x'], user_functions={'f': lambda x: x * x}) assert grader(None, 'x^2')['ok'] grader = FormulaGrader(answers="f''(x)", variables=['x'], user_functions={"f''": lambda x: x * x}) assert grader(None, "f''(x)")['ok'] grader = FormulaGrader(answers="x^2", variables=['x'], user_functions={"sin": lambda x: x * x}) assert grader(None, 'sin(x)')['ok'] grader = FormulaGrader(answers="f(x)", variables=['x'], user_functions={"f": [np.sin, np.cos]}) assert grader(None, 'f(x)')['ok'] grader = FormulaGrader(answers="f''(x) + omega^2*f(x)", variables=['x', 'omega'], user_functions={ "f": RandomFunction(), "f''": RandomFunction() }) assert grader(None, "f''(x)+omega^2*f(x)")['ok'] grader = FormulaGrader(answers='1/sqrt(1-v^2/c^2)', variables=['v'], user_constants={'c': 3e8}) assert grader(None, '1/sqrt(1-v^2/c^2)')['ok'] grader = FormulaGrader( answers='2*sin(theta)*cos(theta)', variables=['theta'], forbidden_strings=[ '*theta', 'theta*', 'theta/', '+theta', 'theta+', '-theta', 'theta-' ], forbidden_message= "Your answer should only use trigonometric functions acting on theta, not multiples of theta" ) assert grader(None, '2*sin(theta)*cos(theta)')['ok'] grader = FormulaGrader(answers='2*sin(theta)*cos(theta)', variables=['theta'], tolerance=0.00001) assert grader(None, '2*sin(theta)*cos(theta)')['ok'] grader = FormulaGrader(answers='2*sin(theta)*cos(theta)', variables=['theta'], case_sensitive=False) assert grader(None, '2*Sin(theta)*Cos(theta)')['ok'] grader = FormulaGrader(answers='2*m', variables=['m'], metric_suffixes=True) assert grader(None, '2*m')['ok'] assert not grader(None, '2m')['ok']
def test_fg_debug_log(): set_seed(0) grader = FormulaGrader(answers='x^2 + f(y) + z', variables=['x', 'y', 'z'], sample_from={'z': ComplexRectangle()}, blacklist=['sin', 'cos', 'tan'], user_functions={ 'f': RandomFunction(), 'square': squareit }, samples=2, debug=True) result = grader(None, 'z + x*x + f(y)') message = ( "<pre>MITx Grading Library Version {version}<br/>\n" "Running on edX using python {python_version}<br/>\n" "Student Response:<br/>\n" "z + x*x + f(y)<br/>\n" "<br/>\n" "==============================================================<br/>\n" "FormulaGrader Debug Info<br/>\n" "==============================================================<br/>\n" "Functions available during evaluation and allowed in answer:<br/>\n" "{{{u}'abs': <function absolute at 0x...>,<br/>\n" " {u}'arccos': <function arccos at 0x...>,<br/>\n" " {u}'arccosh': <function arccosh at 0x...>,<br/>\n" " {u}'arccot': <function arccot at 0x...>,<br/>\n" " {u}'arccoth': <function arccoth at 0x...>,<br/>\n" " {u}'arccsc': <function arccsc at 0x...>,<br/>\n" " {u}'arccsch': <function arccsch at 0x...>,<br/>\n" " {u}'arcsec': <function arcsec at 0x...>,<br/>\n" " {u}'arcsech': <function arcsech at 0x...>,<br/>\n" " {u}'arcsin': <function arcsin at 0x...>,<br/>\n" " {u}'arcsinh': <function arcsinh at 0x...>,<br/>\n" " {u}'arctan': <function arctan at 0x...>,<br/>\n" " {u}'arctan2': <function arctan2 at 0x...>,<br/>\n" " {u}'arctanh': <function arctanh at 0x...>,<br/>\n" " {u}'ceil': <function ceil at 0x...>,<br/>\n" " {u}'conj': <ufunc 'conjugate'>,<br/>\n" " {u}'cosh': <function cosh at 0x...>,<br/>\n" " {u}'cot': <function cot at 0x...>,<br/>\n" " {u}'coth': <function coth at 0x...>,<br/>\n" " {u}'csc': <function csc at 0x...>,<br/>\n" " {u}'csch': <function csch at 0x...>,<br/>\n" " {u}'exp': <function exp at 0x...>,<br/>\n" " {u}'f': <function random_function at 0x...>,<br/>\n" " {u}'fact': <function factorial at 0x...>,<br/>\n" " {u}'factorial': <function factorial at 0x...>,<br/>\n" " {u}'floor': <function floor at 0x...>,<br/>\n" " {u}'im': <function imag at 0x...>,<br/>\n" " {u}'kronecker': <function kronecker at 0x...>,<br/>\n" " {u}'ln': <function log at 0x...>,<br/>\n" " {u}'log10': <function log10 at 0x...>,<br/>\n" " {u}'log2': <function log2 at 0x...>,<br/>\n" " {u}'max': <function max at 0x...>,<br/>\n" " {u}'min': <function min at 0x...>,<br/>\n" " {u}'re': <function real at 0x...>,<br/>\n" " {u}'sec': <function sec at 0x...>,<br/>\n" " {u}'sech': <function sech at 0x...>,<br/>\n" " {u}'sinh': <function sinh at 0x...>,<br/>\n" " {u}'sqrt': <function sqrt at 0x...>,<br/>\n" " {u}'square': <function squareit at 0x...>,<br/>\n" " {u}'tanh': <function tanh at 0x...>}}<br/>\n" "Functions available during evaluation and disallowed in answer:<br/>\n" "{{{u}'cos': <function cos at 0x...>,<br/>\n" " {u}'sin': <function sin at 0x...>,<br/>\n" " {u}'tan': <function tan at 0x...>}}<br/>\n" "<br/>\n" "<br/>\n" "==========================================<br/>\n" "Evaluation Data for Sample Number 1 of 2<br/>\n" "==========================================<br/>\n" "Variables:<br/>\n" "{{{u}'e': 2.718281828459045,<br/>\n" " {u}'i': 1j,<br/>\n" " {u}'j': 1j,<br/>\n" " {u}'pi': 3.141592653589793,<br/>\n" " {u}'x': 3.195254015709299,<br/>\n" " {u}'y': 3.860757465489678,<br/>\n" " {u}'z': (2.205526752143288+2.0897663659937935j)}}<br/>\n" "Student Eval: (14.7111745179+2.08976636599j)<br/>\n" "Compare to: [(14.711174517877566+2.0897663659937935j)]<br/>\n" "<br/>\n" "<br/>\n" "==========================================<br/>\n" "Evaluation Data for Sample Number 2 of 2<br/>\n" "==========================================<br/>\n" "Variables:<br/>\n" "{{{u}'e': 2.718281828459045,<br/>\n" " {u}'i': 1j,<br/>\n" " {u}'j': 1j,<br/>\n" " {u}'pi': 3.141592653589793,<br/>\n" " {u}'x': 2.694619197355619,<br/>\n" " {u}'y': 3.5835764522666245,<br/>\n" " {u}'z': (1.875174422525385+2.7835460015641598j)}}<br/>\n" "Student Eval: (11.9397106851+2.78354600156j)<br/>\n" "Compare to: [(11.93971068506166+2.7835460015641598j)]<br/>\n" "<br/>\n" "<br/>\n" "==========================================<br/>\n" "Comparison Data for All 2 Samples<br/>\n" "==========================================<br/>\n" "Comparer Function: EqualityComparer({{{u}'transform': <function identity_transform at 0x...>}})<br/>\n" "Comparison Results:<br/>\n" "[{{{u}'grade_decimal': 1.0, {u}'msg': {u}'', {u}'ok': True}},<br/>\n" " {{{u}'grade_decimal': 1.0, {u}'msg': {u}'', {u}'ok': True}}]<br/>\n" "</pre>").format(version=VERSION, python_version=platform.python_version(), u=UNICODE_PREFIX) message = message.replace("<func", "<func").replace("...>", "...>") expected = round_decimals_in_string(message) result_msg = round_decimals_in_string(result['msg']).replace( 'test_fg_debug_log.<locals>.', '') assert expected == result_msg