def test_check_object_keys(): s = setup_state('x = {"a": 2}', 'x = {"a": 2}') with pytest.raises( InstructorError, match=r"`check_keys\(\)` couldn't find key `b` in object `x` in the solution process\.", ): s.check_object("x").check_keys("b")
def test_check_object_is_instance(): s = setup_state("x = 1", "x = 1") with pytest.raises( InstructorError, match=r"`is_instance\(\)` noticed that `x` is not a `str` in the solution process\.", ): s.check_object("x").is_instance(str)
def test_test_custom_equality_func(tol, passes): s = setup_state("a = [1.011]", "a = [1.01]") import numpy as np with helper.verify_sct(passes): s.check_object("a").has_equal_value( func=lambda x, y: np.allclose(x, y, atol=tol))
def test_check_call_lambda(stu, passes): s = setup_state(stu, "lambda a, b: a + b") with helper.verify_sct(passes): s.check_lambda_function().multi( check_call("f(1,2)").has_equal_value(), check_call("f(1,2)").has_equal_output(), )
def test_has_import(): s = setup_state() with pytest.raises( InstructorError, match=r"`has_import\(\)` couldn't find an import of the package numpy in your solution code\.", ): s.has_import("numpy")
def test_check_object(): s = setup_state() with pytest.raises( InstructorError, match=r"`check_object\(\)` couldn't find object `x` in the solution process\.", ): s.check_object("x")
def check_function_multiple_times(): from pythonwhat.local import setup_state s = setup_state(sol_code="print('test')", stu_code="print('test')") helper.passes(s.check_function("print")) helper.passes(s.check_function("print").check_args(0)) helper.passes(s.check_function("print").check_args("value"))
def test_assert_ast(element, no_error): s = setup_state()._state if no_error: assert_ast(s, element, {}) else: with pytest.raises(InstructorError): assert_ast(s, element, {})
def test_args_kwargs_check_function_passing(argspec): code = "my_fun(1, 2, 3, 4, c = 5)" s = setup_state(pec="def my_fun(a, b, *args, **kwargs): pass", stu_code=code, sol_code=code) x = s.check_function("my_fun") helper.passes(x.check_args(argspec).has_equal_value())
def test_running_file_with_root_check(temp_py_file): content = cf.get_file_content(temp_py_file.name) chain = setup_state("", "", pec="") with tempfile.TemporaryDirectory() as d: with ChDir(d): chain.check_file(temp_py_file.name, solution_code=content).run().check_object( "a").has_equal_value() with tempfile.TemporaryDirectory() as d: with ChDir(d): chain.check_file(temp_py_file.name, solution_code=content).run().has_no_error() with tempfile.TemporaryDirectory() as d: with ChDir(d): chain.check_file(temp_py_file.name, solution_code=content).run().has_printout(0) with pytest.raises(TF): with tempfile.TemporaryDirectory() as d: with ChDir(d): chain.check_file( temp_py_file.name, solution_code="print('Bye!')").run().has_printout(0) with tempfile.TemporaryDirectory() as d: with ChDir(d): chain.check_file(temp_py_file.name, solution_code=content).run().has_output("Hi")
def test_running_file(temp_py_file): content = cf.get_file_content(temp_py_file.name) chain = setup_state("", "", pec="") with tempfile.TemporaryDirectory() as d: with ChDir(d): chain.check_file( temp_py_file.name, solution_code=content).run().has_equal_value(expr_code="a") with tempfile.TemporaryDirectory() as d: with ChDir(d): chain.check_file(temp_py_file.name, solution_code=content).run().check_object( "a").has_equal_value() with pytest.raises(TF): with tempfile.TemporaryDirectory() as d: with ChDir(d): chain.check_file(temp_py_file.name, solution_code=content.replace( "1", "2")).run().has_equal_value(expr_code="a") with tempfile.TemporaryDirectory() as d: with ChDir(d): chain.check_file(temp_py_file.name).run().has_equal_value( expr_code="a", override=1) with pytest.raises(TF): with tempfile.TemporaryDirectory() as d: with ChDir(d): chain.check_file(temp_py_file.name).run().has_equal_value( expr_code="a", override=2)
def test_has_printout(): s = setup_state() with pytest.raises( InstructorError, match=r"`has_printout\(1\)` couldn't find the second print call in your solution\.", ): s.has_printout(1)
def test_run_with_absolute_dir(): code = 'from pathlib import Path; c = Path("c").read_text(encoding="utf-8")' file_dir = "a/b" solution_location = "solution" workspace_location = "workspace" with in_temp_dir(): os.makedirs(file_dir) with ChDir(file_dir): abs_dir = os.path.abspath(".") abs_file_path = Path(abs_dir, "c") with open("c", "w") as f: f.write(code) write_file(solution_location, "c", code) os.makedirs(workspace_location) with ChDir(workspace_location): chain = setup_state("", "", pec="") child = chain.check_file(abs_file_path, solution_code=code) child.run(abs_dir).check_object("c") child.run().check_object("c")
def test_check_function_def_basic(stu, passes): s = setup_state(stu, "def test(x): print(x)") with helper.verify_sct(passes): s.check_function_def("test").multi( check_args(0).has_equal_part("name", msg="wrong"), check_body().set_context(1).check_function("print").check_args( 0).has_equal_value(), )
def check_function_sig_false(): code = "f(color = 'blue')" s = setup_state(pec="def f(*args, **kwargs): pass", sol_code=code, stu_code=code) helper.passes( s.check_function("f", 0, signature=False).check_args("color").has_equal_ast())
def test_two_for_loops(stu, passes): s = setup_state(stu, "for i in range(1):\n pass\nfor j in range(4): print(j)") with helper.verify_sct(passes): s.check_for_loop(index=1).multi( check_iter().has_equal_value(), check_body().set_context(2).has_equal_output(), )
def test_context_vals_wrong_place_in_chain(): code = "[(i,j) for i,j in enumerate(range(10))]" state = setup_state(code, code) with pytest.raises( InstructorError, match=r"`set_context\(\)` failed: context val names are missing, but you tried to set \['i', 'j'\]\.", ): state.check_list_comp(0).set_context(i=1, j=2).check_iter()
def test_check_call_not_on_check_function_def(): code = "def x(a): pass" s = setup_state(code, code) with pytest.raises( InstructorError, match=r"`check_call\(\)` can only be called on `check_function_def\(\)` or `check_lambda_function\(\)`\.", ): s.check_object("x").check_call("f(1)")
def test_check_keys_not_on_check_object(): code = "round(3)" s = setup_state(code, code) with pytest.raises( InstructorError, match=r"`is_instance\(\)` can only be called on `check_object\(\)` or `check_df\(\)`\.", ): s.check_function("round").check_args(0).check_keys("a")
def test_has_no_error_not_on_root(): code = "for i in range(3): pass" s = setup_state(code, code) with pytest.raises( InstructorError, match=r"`has_no_error\(\)` should only be called focusing on a full script, following `Ex\(\)` or `run\(\)`\.", ): s.check_for_loop().check_body().has_no_error()
def test_has_printout_not_on_root(): code = "for i in range(3): print(i)" s = setup_state(code, code) with pytest.raises( InstructorError, match=r"`has_printout\(\)` should only be called focusing on a full script, following `Ex\(\)` or `run\(\)`\. If you want to check printouts done in e.g. a for loop, you have to use a `check_function\('print'\)` chain instead.", ): s.check_for_loop().check_body().has_printout(0)
def test_set_context(): code = "x = { m:len(m) for m in ['a', 'b', 'c'] }" s = setup_state(code, code) with pytest.raises( InstructorError, match=r"In `set_context\(\)`, specify arguments either by position, either by name\.", ): s.check_dict_comp().check_key().set_context("a", m="a").has_equal_value()
def test_file_parsing(temp_py_file): expected_content = cf.get_file_content(temp_py_file.name) chain = setup_state("", "", pec="") file_chain = chain.check_file(temp_py_file.name, solution_code=expected_content) file_chain.check_if_else().check_test().has_equal_value() file_chain.check_if_else().check_test().has_equal_value(expr_code="False")
def test_manual_converter_2(): s = setup_state( stu_code="my_array = np.array([[0,0], [0,0], [0,0]])", sol_code="my_array = np.array([[1,2], [3,4], [5,6]])", pec="import numpy as np", ) set_converter(key="numpy.ndarray", fundef=lambda x: x.shape) s.check_object("my_array").has_equal_value()
def test_test_function_v2_no_sig(): s = setup_state("np.arange(10)", "np.arange(10)", pec="import numpy as np") # test_function_v2 sets signature=False if no params s.test_function_v2("numpy.arange") # check_function fails unless explicity setting signature=Fa s.check_function("numpy.arange", signature=False) with pytest.raises(InstructorError): s.check_function("numpy.arange")
def test_running_code_isolation_run(sol_code, stu_code): # test that setup_state is isolated chain = setup_state(sol_code, stu_code, pec="") chain._state.solution_code = sol_code chain._state.student_code = stu_code with verify_sct(False): # test that run is isolated chain.run().has_equal_value(name="bar", override="bar")
def test_check_class_def_pass(stu, passes): sol = "class A(str):\n def __init__(self): pass" s = setup_state(stu, sol) with helper.verify_sct(passes): s.check_class_def("A").multi( check_bases(0).has_equal_ast(), check_body().check_function_def( "__init__").check_body().has_equal_ast(), )
def test_urlopen_in_process(sol_code, stu_code): with in_temp_dir(): chain = setup_state("", "", pec="") chain._state.solution_code = sol_code chain._state.student_code = stu_code with verify_sct(True): chain.run()
def test_args_kwargs_check_function_failing_not_specified(argspec, msg): s = setup_state( pec="def my_fun(a, b, *args, **kwargs): pass", sol_code="my_fun(1, 2, 3, 4, c = 5)", stu_code="my_fun(1, 2)", ) x = s.check_function("my_fun") with pytest.raises(TF, match=msg): x.check_args(argspec)
def test_args_kwargs_check_function_failing_not_correct(argspec, msg): s = setup_state( pec="def my_fun(a, b, *args, **kwargs): pass", sol_code="my_fun(1, 2, 3, 4, c = 5)", stu_code="my_fun(1, 2, 4, 5, c = 6)", ) x = s.check_function("my_fun") with pytest.raises(TF, match=msg): x.check_args(argspec).has_equal_value()