5

I'm trying to write a testing program to test many(identical) student assignments. I have a test written using the unittest library. The documentation seems to indicate that each test should be associated with one file. Instead, I'd like to have one test file and use command line arguments to point the test to the file it should test.

I know I can do this by using the argparse module in my unit tests, but is there a better way? It seems like this behavior should be supported in unittest, but I can't find anything in the documentation...

3
  • What are the requirements of the assignment? Commented Feb 12, 2020 at 18:59
  • My answer depends on what you are trying to test exactly. Commented Feb 12, 2020 at 19:00
  • @ReinstateMonica The assignment requires students to take input (str) from stdin, do some calculations, and return the appropriate value (str) to stdout. The test I designed runs the given file (which is currently hardcoded) as a subprocess, and uses subprocess.communicate to do IPC (interprocess communication). Commented Feb 12, 2020 at 19:02

2 Answers 2

1

Create the Main test directory and add sub test packages. Have a test runner created for you pointing to the test directory. It could act as a suite. I have attached a piece of code that I have used for my test suite.

import os
import unittest

def main(test_path, test_pattern):
    print(('Discovering tests in : {}'.format(test_path)))
    suite = unittest.TestLoader().discover(test_path, test_pattern)
    unittest.TextTestRunner(verbosity=2).run(suite)

if __name__ == '__main__':
    root_path = os.path.abspath('.')
    test_path = os.path.join(root_path, 'src/tests/')
    test_pattern = 'test_*'
    main(test_path, test_pattern)

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks I'll give this a try later today.
1

Generally speaking, unittest is used to test module level python code, not interactions python code has with external programs. AFAIK, writing to stdout (ie. print) means you are either debugging or passing information to another program.

In your case, I don't think unittest is really necessary, unless you want to give assignments that are to "pass this unittest" (which is common in the wild).

Instead I would simply iterate over the directory that contains the assignments, check the stdout using subprocess, then write the results to a csv file:

import subprocess
import os
import csv

ASSIGNMENT_DIR = '/path/to/assignments'

expected_stdout = 'Hello World!'

def _determine_grade(stdout):
    if stdout == expected_stdout:
        return '100%'
    return '0%'  

grades = {}   

for assignment in os.listdir(ASSIGNMENT_DIR):
    filepath = os.path.join(ASSIGNMENT_DIR, assignment)

    stdout = subprocesss.check_output(f'python3 {filepath}', shell=True)

    grade = _determine_grade(stdout)
    grades.append({'assignment':assignment, 'grade':grade})

with open('/path/to/grades.csv', 'w+') as f:
    w = csv.DictWriter(f, ('assignment', 'grade'))
    w.writeheader()
    w.writerows(grades)

2 Comments

This could also easily be normalized to work with any assignment, which I could show you, if you want.
Thanks for the answer. I agree that this works fine. The reason I decided to use unittest is due to the fact that a student's code may work in some cases and not others. Thus I have several test cases to run on each assignment, each of which checks for a different kind of error. Once one has defined the test cases, unittest automatically runs them all and reports the results of each test in a nicely formatted manner, which is alot of boilerplate I don't have to write. In the future, I would like to give my students the test to run themselves to add a sense of "realism".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.