import inspect
import file_to_test as submission
codelines = inspect.getsourcelines(submission)[0]
to_proof = [line.strip() for line in codelines if line.strip().lower().startswith("is_identical")][-1]
# test_foo.py
from unittest import TestCase
from unittest.mock import patch
from importlib import reload
class FooTest(TestCase):
def test_comparison_used(self):
import foo
self.assertFalse(foo.is_identical)
with patch("foo.id") as id_:
reload(foo)
id_().__eq__.assert_called()
当foo.py使用“作弊”方法时:
#!/usr/bin/env python
x = 42
y = 43
is_identical = False # id(x) == id(y)
我得到E AssertionError: Expected '__eq__' to have been called.
In [130]: def catch_trick_bool(unit_test_result=None, student_compare=None,student_trick=None):
...: student = str(input("Enter student name: "))
...: # import dis - Use this to further examine code objects.
...: # Eg. use dis.dis(co_unit_test) to view the code objects for
...: # the unit test expresssion
...: if unit_test_result:
...: co_unit_test = compile(unit_test_result, 'none', 'single')
...: if False in co_unit_test.co_consts:
...: print("Bool value 'False' returned from Unit Test")
...: elif student_compare:
...: co_student_compare = compile(student_compare, 'none', 'single')
...: if '6b' in co_student_compare.co_code.hex():
...: print("Student {} performed the comparison successfully".format(student))
...: else:
...: co_student_trick = compile(student_trick, 'none', 'single')
...: if False in co_student_trick.co_consts:
...: print("Student {} tried to set a bool value of 'False' for the test".format(student))
...:
In [131]: catch_trick_bool(unit_test_result='is_identical_unit_test = False')
Enter student name: John
Bool value 'False' returned from Unit Test
In [132]: catch_trick_bool(student_trick='is_identical_student_trick = False')
Enter student name: John
Student John tried to set a bool value of 'False' for the test
In [133]: catch_trick_bool(student_compare='id(x) == id(y)')
Enter student name: John
Student John performed the comparison successfully
我对answer from amanb很满意。不过,在此期间,我也找到了一个解决办法,给了我很好的效果。我用^{} 代替了库^{} 。你知道吗
此外,这是获得源代码相关部分的一种方法,无需硬编码
is_identical = …
(为了清楚起见,如果给定了变量,则无需检查):这个恶作剧的猴子补丁似乎解决了:
当
foo.py
使用“作弊”方法时:我得到
E AssertionError: Expected '__eq__' to have been called.
但是如果我做了
is_identical = id(x) == id(y)
,那么测试就通过了。你知道吗下面的解决方案使用代码对象中的常量来标识bool值True/False,并使用字节码指令
'COMPARE_OP'
来标识比较操作。可以对代码进行改进以添加更多案例,但这只是给您一个开始。为了显示所有条件,我将函数中的所有参数都设置为可选:解释:
下面显示如何在代码对象的字节码指令的十六进制表示中搜索十六进制字节码
0x6b
。这个字节码对应于opname'COMPARE_OP'
。此指令指示代码中的比较操作。你知道吗类似地,bool值被解析为
LOAD_CONST
字节码指令,这些指令可以通过co_consts
轻松访问:结论:
分解的代码对象可以帮助识别布尔值的来源。如果在上述情况下显式定义了bool值,那么bool值将被解析为常量
LOAD_CONST
字节码指令。如果它是通过使用比较的布尔表达式(如5>;2)隐式推导的,则代码将解析为特定的字节码指令COMPARE_OP
,以指示比较操作。您可以进一步扩展代码以检查truthy值,并根据需要进行修改。你知道吗相关问题 更多 >
编程相关推荐