Skip to content

Commit ac0c6bc

Browse files
committed
Create test cases easily for C CPP
While creating a C or CPP standard function based question, the standard test case will simply be the assert function of CPP. This replaces the writing of complete C code and print inputs and expected output for the user code evaluation. Now the creator simply needs to write the assert function. Example: For add function (adding two numbers), the test case will be: assert(add(1, 2) == 3)
1 parent c9e0d0d commit ac0c6bc

File tree

3 files changed

+40
-158
lines changed

3 files changed

+40
-158
lines changed

yaksh/cpp_code_evaluator.py

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os
44
from os.path import isfile
55
import subprocess
6+
from textwrap import dedent
67

78
# Local imports
89
from .file_utils import copy_files, delete_files
@@ -49,16 +50,42 @@ def set_file_paths(self):
4950

5051
return user_output_path, ref_output_path
5152

53+
def append_test_case_to_answer(self):
54+
content = dedent('''
55+
{0}
56+
#include <cassert>
57+
int main(){{
58+
{1};
59+
return 0;
60+
}}
61+
'''.format(self.user_answer, self.test_case))
62+
return content
63+
5264
def get_commands(self, clean_ref_code_path, user_output_path,
5365
ref_output_path):
54-
compile_command = 'g++ {0} -c -o {1}'.format(
66+
compile_command = 'g++ {0} -c -o {1}'.format(
5567
self.submit_code_path, user_output_path)
56-
compile_main = 'g++ {0} {1} -o {2}'.format(
57-
clean_ref_code_path, user_output_path,
58-
ref_output_path
68+
compile_main = 'g++ {0} -o {1}'.format(
69+
clean_ref_code_path, ref_output_path
5970
)
6071
return compile_command, compile_main
6172

73+
def trim_error(self, error_type, error):
74+
err = error_type
75+
try:
76+
error_lines = error.splitlines()
77+
for e in error_lines:
78+
if ':' in e:
79+
if error_type == 'Assertion Error:':
80+
err = '{0} \n {1}'.format(err, e.split(':')[-1])
81+
else:
82+
err = '{0} \n {1}'.format(err, e.split(':', 1)[1])
83+
else:
84+
err = '{0} \n {1}'.format(err, e)
85+
except Exception:
86+
return '{0} \n {1}'.format(err, main_err)
87+
return err
88+
6289
def compile_code(self):
6390
if self.compiled_user_answer and self.compiled_test_code:
6491
return None
@@ -67,7 +94,8 @@ def compile_code(self):
6794
self.test_code_path = self.create_submit_code_file('main.c')
6895
self.write_to_submit_code_file(self.submit_code_path,
6996
self.user_answer)
70-
self.write_to_submit_code_file(self.test_code_path, self.test_case)
97+
main_content = self.append_test_case_to_answer()
98+
self.write_to_submit_code_file(self.test_code_path, main_content)
7199
clean_ref_code_path = self.test_code_path
72100
if self.file_paths:
73101
self.files = copy_files(self.file_paths)
@@ -90,7 +118,6 @@ def compile_code(self):
90118
stdout=subprocess.PIPE,
91119
stderr=subprocess.PIPE
92120
)
93-
94121
self.compiled_test_code = self._run_command(
95122
self.compile_main,
96123
shell=True,
@@ -141,31 +168,13 @@ def check_code(self):
141168
success, err = True, None
142169
mark_fraction = 1.0 if self.partial_grading else 0.0
143170
else:
144-
err = "{0} \n {1}".format(stdout, stderr)
171+
err = self.trim_error('Assertion Error:', stderr)
145172
raise AssertionError(err)
146173
else:
147-
err = "Test case Error:"
148-
try:
149-
error_lines = main_err.splitlines()
150-
for e in error_lines:
151-
if ':' in e:
152-
err = "{0} \n {1}".format(err, e.split(":", 1)[1])
153-
else:
154-
err = "{0} \n {1}".format(err, e)
155-
except Exception:
156-
err = "{0} \n {1}".format(err, main_err)
174+
err = self.trim_error('Test case Error:', main_err)
157175
raise TestCaseError(err)
158176
else:
159-
err = "Compilation Error:"
160-
try:
161-
error_lines = stdnt_stderr.splitlines()
162-
for e in error_lines:
163-
if ':' in e:
164-
err = "{0} \n {1}".format(err, e.split(":", 1)[1])
165-
else:
166-
err = "{0} \n {1}".format(err, e)
167-
except Exception:
168-
err = "{0} \n {1}".format(err, stdnt_stderr)
177+
err = self.trim_error('Compilation Error:', stdnt_stderr)
169178
raise CompilationError(err)
170179

171180
return success, err, mark_fraction

yaksh/evaluator_tests/test_c_cpp_evaluation.py

Lines changed: 4 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -18,40 +18,7 @@ def setUp(self):
1818
with open(self.f_path, 'wb') as f:
1919
f.write('2'.encode('ascii'))
2020
tmp_in_dir_path = tempfile.mkdtemp()
21-
self.tc_data = dedent("""
22-
#include <stdio.h>
23-
#include <stdlib.h>
24-
25-
extern int add(int, int);
26-
27-
template <class T>
28-
29-
void check(T expect, T result)
30-
{
31-
if (expect == result)
32-
{
33-
printf("Correct: Expected %d got %d ",expect,result);
34-
}
35-
else
36-
{
37-
printf("Incorrect: Expected %d got %d ",expect,result);
38-
exit (1);
39-
}
40-
}
41-
42-
int main(void)
43-
{
44-
int result;
45-
result = add(0,0);
46-
printf("Input submitted to the function: 0, 0");
47-
check(0, result);
48-
result = add(2,3);
49-
printf("Input submitted to the function: 2 3");
50-
check(5,result);
51-
printf("All Correct");
52-
return 0;
53-
}
54-
""")
21+
self.tc_data = 'assert(add(2, 3) == 5)'
5522
self.test_case_data = [{"test_case": self.tc_data,
5623
"test_case_type": "standardtestcase",
5724
"weight": 0.0
@@ -157,33 +124,7 @@ def test_infinite_loop(self):
157124
def test_file_based_assert(self):
158125
# Given
159126
self.file_paths = [(self.f_path, False)]
160-
self.tc_data = dedent("""
161-
#include <stdio.h>
162-
#include <stdlib.h>
163-
164-
extern int ans();
165-
166-
template <class T>
167-
void check(T expect,T result)
168-
{
169-
if (expect == result)
170-
{
171-
printf("Correct: Expected %d got %d ",expect,result);
172-
}
173-
else
174-
{
175-
printf("Incorrect: Expected %d got %d ",expect,result);
176-
exit (0);
177-
}
178-
}
179-
180-
int main(void)
181-
{
182-
int result;
183-
result = ans();
184-
check(50, result);
185-
}
186-
""")
127+
self.tc_data = 'assert(ans() == 50)'
187128
self.test_case_data = [{"test_case": self.tc_data,
188129
"test_case_type": "standardtestcase",
189130
"weight": 0.0
@@ -218,40 +159,7 @@ def test_file_based_assert(self):
218159

219160
def test_incorrect_testcase(self):
220161
# Given
221-
self.tc_data = dedent("""
222-
#include <stdio.h>
223-
#include <stdlib.h>
224-
225-
extern int add(int, int);
226-
227-
template <class T>
228-
229-
void check(T expect, T result)
230-
{
231-
if (expect == result)
232-
{
233-
printf("Correct: Expected %d got %d ",expect,result);
234-
}
235-
else
236-
{
237-
printf("Incorrect: Expected %d got %d ",expect,result);
238-
exit (1);
239-
}
240-
}
241-
242-
int main(void)
243-
{
244-
int result;
245-
result = add(0,0);
246-
printf("Input submitted to the function: 0, 0");
247-
check(0, result);
248-
result = add(2,3);
249-
printf("Input submitted to the function: 2 3");
250-
check(5,result)
251-
printf("All Correct");
252-
return 0;
253-
}
254-
""")
162+
self.tc_data = 'assert(add(0, 1) == 1'
255163
user_answer = dedent("""\
256164
int add(int a, int b)
257165
{
@@ -828,42 +736,7 @@ def test_assert_with_hook(self):
828736
# Given
829737
user_answer = "int add(int a, int b)\n{return a+b;}"
830738

831-
assert_test_case = dedent("""\
832-
#include <stdio.h>
833-
#include <stdlib.h>
834-
835-
extern int add(int, int);
836-
837-
template <class T>
838-
839-
void check(T expect, T result)
840-
{
841-
if (expect == result)
842-
{
843-
printf("Correct: Expected %d got %d ",
844-
expect,result);
845-
}
846-
else
847-
{
848-
printf("Incorrect: Expected %d got %d ",
849-
expect,result);
850-
exit (1);
851-
}
852-
}
853-
854-
int main(void)
855-
{
856-
int result;
857-
result = add(0,0);
858-
printf("Input submitted 0, 0");
859-
check(0, result);
860-
result = add(2,3);
861-
printf("Input submitted 2 3");
862-
check(5,result);
863-
printf("All Correct");
864-
return 0;
865-
}
866-
""")
739+
assert_test_case = 'assert(add(2, 3) == 5)'
867740

868741
hook_code = dedent("""\
869742
def check_answer(user_answer):

yaksh/fixtures/demo_questions.zip

-7.27 KB
Binary file not shown.

0 commit comments

Comments
 (0)