Hello all,
I have been creating questions with a custom template to compile, run, and test C programs.
I want there to be a range of marks that become progressively more difficult, and I want students to be able to get partial marks. I can't see anywhere how to do this -- I am wondering if I need to do it a different way when using a custom template?
I've attached the template below.
Thanks, Angus
""" The template for a question type that compiles and runs a student-submitted
C program.
"""
import subprocess, sys
# Write the student code to a file prog.c
student_answer = """{{ STUDENT_ANSWER | e('py') }}"""
test_argument = """{{ TEST.stdin | e('py') }}"""
with open("cakeSlice.c", "w") as src:
print(student_answer, file=src)
# Compile
{% if QUESTION.parameters.cflags is defined %}
cflags = """{{ QUESTION.parameters.cflags | e('py') }}"""
{% else %}
cflags = "-std=c99 -Wall -Werror"
{% endif %}
return_code = subprocess.call("gcc {0} -o cakeSlice cakeSlice.c".format(cflags).split())
if return_code != 0:
print("** Compilation failed. Testing aborted **", file=sys.stderr)
# If compile succeeded, run the code. Since this is a per-test template,
# stdin is already set up for the stdin text specified in the test case,
# so we can run the compiled program directly.
if return_code == 0:
bash_command = """{{ TEST.testcode | e('py') }}"""
try:
output = subprocess.check_output(bash_command, shell=True, universal_newlines=True)
print(output)
except subprocess.CalledProcessError as e:
if e.returncode > 0:
# Ignore non-zero positive return codes
if e.output:
print(e.output)
else:
# But negative return codes are signals - abort
if e.output:
print(e.output, file=sys.stderr)
if e.returncode < 0:
print("Task failed with signal", -e.returncode, file=sys.stderr)
print("** Further testing aborted **", file=sys.stderr)