使用pytest测试和评分学生代码

时间:2014-12-29 19:17:47

标签: python pytest

假设我想使用测试对某些学生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

帮助&欢迎捐款!

2 个答案:

答案 0 :(得分:0)

非常酷和有趣的项目。如果不了解更多,很难回答。

基本上你应该可以通过写custom plugin来做到这一点。您可以将conftest.py放置在测试或项目文件夹中,其中包含您的unittest子文件夹和每个学生的子文件夹。

可能想写两个插件:

  • 允许加权测试(例如test_foo_10和test_bar_5)和计算最终成绩(例如490/520)(teamcity-messages是使用same hooks的示例)
  • 另一个允许将测试分发到单独的进程。 (xdist为例)

我知道这不是一个非常完整的答案,但我想至少指出最后一点。由于学生使用重叠模块名称的可能性非常高,因此他们会在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()