假设我想使用测试对某些学生python代码进行评分,例如(这是我希望我能编写的伪代码):
code = __import__("student_code") # Import the code to be tested
grade = 100
for test in all_tests(): # Loop over the tests that were gathered
good = perform(test, code) # Perform the test individually on the code
if not good: # Do something if the code gives the wrong result
grade -= 1
为此,我想使用pytest
(易于编写好的测试),但有许多事情我不知道该怎么做:
code
从学生代码中导入)all_tests()
)perform(test, code)
)我无法找到与此用户相关的任何内容(pytest.main()
无论如何似乎都无法解决问题......)
我希望你看到我的观点,干杯!
修改
我终于找到了如何执行我的第一点(对外部代码进行测试)。在要执行测试的存储库中,使用以下命令生成conftest.py
文件:
import imp # Import standard library
import pytest
def pytest_addoption(parser):
"""Add a custom command-line option to py.test."""
parser.addoption("--module", help="Code file to be tested.")
@pytest.fixture(scope='session')
def module(request):
"""Import code specified with the command-line custom option '--module'."""
codename = request.config.getoption("--module")
# Import module (standard __import__ does not support import by filename)
try:
code = imp.load_source('code', codename)
except Exception as err:
print "ERROR while importing {!r}".format(codename)
raise
return code
然后,使用tests.py
夹具在module
文件中收集测试:
def test_sample(module):
assert module.add(1, 2) == 3
最后,使用py.test tests.py --module student.py
运行测试。
我还在第2点和第3点工作。
编辑2
我在这个问题上传了我的(不完整)内容:
https://gitlab.in2p3.fr/ycopin/pyTestExam
帮助&欢迎捐款!
答案 0 :(得分:0)
非常酷和有趣的项目。如果不了解更多,很难回答。
基本上你应该可以通过写custom plugin来做到这一点。您可以将conftest.py
放置在测试或项目文件夹中,其中包含您的unittest子文件夹和每个学生的子文件夹。
可能想写两个插件:
我知道这不是一个非常完整的答案,但我想至少指出最后一点。由于学生使用重叠模块名称的可能性非常高,因此他们会在pytest世界中发生冲突,首先收集测试,然后在尝试不重新导入具有通用名称的模块的过程中运行。
即使你试图控制它,你最终也会让学生以一种草率的方式操纵全局命名空间,这可能导致另一个学生代码失败。出于这个原因,您将需要一个bash脚本来运行每个学生文件或一个插件,它将在不同的进程中运行它们。
让这个用例成为一个分级的实习考试,看看他们想出了什么:-) ... naaah ......但你可以; - )
答案 1 :(得分:0)
我想出了这样的东西(假设 sum
函数是学生代码):
import unittest
score = 0
class TestAndGrade(unittest.TestCase):
def test_correctness(self):
self.assertEqual(sum([2,2]), 4)
global score; score += 6 # Increase score
def test_edge_cases(self):
with self.assertRaises(Exception):
sum([2,'hello'])
global score; score += 1 # Increase score
# Print the score
@classmethod
def tearDownClass(cls):
global score
print('\n\n-------------')
print('| Score: {} |'.format(score))
print('-------------\n')
# Run the tests
unittest.main()