<commit_before>import sys
import time
import unittest
from utils import OutputLogger, TIMEOUT
from grading import AutograderConsole, run

class AutograderConsoleTest(unittest.TestCase):
    def setUp(self):
        self.logger = sys.stdout = OutputLogger()
        self.console = AutograderConsole(self.logger)

    def tearDown(self):
        sys.stdout = sys.__stdout__

    #############
    # Test exec #
    #############

    def testExec_expectedWithNoErrors(self):
        expr = "x + 4"
        errored = self.console.exec(expr, {'x': 3}, expected='7')
        self.assertFalse(errored)

    def testExec_expectedWithNoEqualsError(self):
        expr = "2 + 4"  # Equals 6, not 7.
        errored = self.console.exec(expr, {}, expected='7')
        self.assertTrue(errored)

    def testExec_expectedExceptionWithNoError(self):
        expr = "1 / 0"  # Causes ZeroDivisionError
        errored = self.console.exec(expr, {},
                expected='ZeroDivisionError')
        self.assertFalse(errored)

    def testExec_expectedExceptionWithNotEqualsError(self):
        expr = "1 + 2"
        errored = self.console.exec(expr, {},
                expected='ZeroDivisionError')
        self.assertTrue(errored)

    def testExec_expectedExceptionWithWrongException(self):
        expr = "1 / 0"
        errored = self.console.exec(expr, {},
                expected='TypeError')
        self.assertTrue(errored)

    def testExec_runtimeError(self):
        expr = "f()"
        max_recursion = lambda: max_recursion()
        errored = self.console.exec(expr, {'f': max_recursion})
        self.assertTrue(errored)

    def testExec_timeoutError(self):
        # TODO(albert): have a better way to test timeout than actually
        # waiting.
        expr = "f()"
        def wait():
            time.sleep(TIMEOUT * 3 // 2)
        errored = self.console.exec(expr, {'f': wait})
        self.assertTrue(errored)

    ############
    # Test run #
    ############

    def testRun_basicLog(self):
        test_case = MockTestCase(
            lines=[
                '$ x + 2',
            ],
            outputs=[
                '4',
            ],
        )
        error, log = self.console.run(test_case, frame={'x': 2})
        self.assertFalse(error)
        self.assertEqual([
            '>>> x + 2', '\n',
            '4', '\n',
        ], log)

    def testRun_basicLogNoFrame(self):<commit_msg>Abstract testExec pattern in grading_tests<commit_after>import sys
import time
import unittest
from utils import OutputLogger, TIMEOUT
from grading import AutograderConsole, run

class AutograderConsoleTest(unittest.TestCase):
    def setUp(self):
        self.logger = sys.stdout = OutputLogger()
        self.console = AutograderConsole(self.logger)

    def tearDown(self):
        sys.stdout = sys.__stdout__

    #############
    # Test exec #
    #############

    def execTest(self, expr, frame, expected=None, should_error=False):
        errored = self.console.exec(expr, frame, expected=expected)
        if should_error:
            self.assertTrue(errored)
        else:
            self.assertFalse(errored)

    def testExec_expectedWithNoErrors(self):
        self.execTest("x + 4", {'x': 3}, '7', False)

    def testExec_expectedWithNoEqualsError(self):
        self.execTest("2 + 4", {}, '7', True)

    def testExec_expectedExceptionWithNoError(self):
        self.execTest("1 / 0", {}, 'ZeroDivisionError', False)

    def testExec_expectedExceptionWithNotEqualsError(self):
        self.execTest("1 + 2", {}, 'ZeroDivisionError', True)

    def testExec_expectedExceptionWithWrongException(self):
        self.execTest("1 / 0", {}, 'TypeError', True)

    def testExec_runtimeError(self):
        max_recursion = lambda: max_recursion()
        self.execTest("f()", {'f': max_recursion}, should_error=True)

    def testExec_timeoutError(self):
        # TODO(albert): have a better way to test timeout than actually
        # waiting.
        def wait():
            time.sleep(TIMEOUT * 3 // 2)
        self.execTest("f()", {'f': wait}, should_error=True)

    ############
    # Test run #
    ############

    def testRun_basicLog(self):
        test_case = MockTestCase(
            lines=[
                '$ x + 2',
            ],
            outputs=[
                '4',
            ],
        )
        error, log = self.console.run(test_case, frame={'x': 2})
        self.assertFalse(error)
        self.assertEqual([
            '>>> x + 2', '\n',
            '4', '\n',
        ], log)

    def testRun_basicLogNoFrame(self):
{'fraction_non_alphanumeric': 0.1393979057591623, 'fraction_numerical': 0.008726003490401396, 'mean_word_length': 2.336972343522562, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5803584', 'n_tokens_mistral': 1407, 'n_tokens_neox': 1326, 'n_words': 285}