diff --git a/MANIFEST.in b/MANIFEST.in index 2fde07c7..90fc938c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -22,10 +22,3 @@ prune */spec prune xblocks_contrib/problem/capa/static/js/capa/spec prune xblocks_contrib/problem/capa/static/js/capa/fixtures prune xblocks_contrib/problem/capa/tests/test_files - -# --- TEST UTILITY INCLUSIONS --- -# Re-include specific test files that are excluded above. -# We do this because openedx-platform imports these specific test helpers. -include xblocks_contrib/problem/capa/tests/test_util.py -include xblocks_contrib/problem/capa/tests/helpers.py -include xblocks_contrib/problem/capa/tests/response_xml_factory.py diff --git a/xblocks_contrib/problem/capa/safe_exec/tests/test_safe_exec.py b/xblocks_contrib/problem/capa/safe_exec/tests/test_safe_exec.py index 90f8420d..bb37b0db 100644 --- a/xblocks_contrib/problem/capa/safe_exec/tests/test_safe_exec.py +++ b/xblocks_contrib/problem/capa/safe_exec/tests/test_safe_exec.py @@ -24,7 +24,7 @@ is_codejail_rest_service_enabled, ) from xblocks_contrib.problem.capa.safe_exec.safe_exec import emsg_normalizers, normalize_error_message -from xblocks_contrib.problem.capa.tests.test_util import UseUnsafeCodejail +from xblocks_contrib.problem.capa.testing.codejail import UseUnsafeCodejail @UseUnsafeCodejail() diff --git a/xblocks_contrib/problem/capa/testing/__init__.py b/xblocks_contrib/problem/capa/testing/__init__.py new file mode 100644 index 00000000..d6754ebc --- /dev/null +++ b/xblocks_contrib/problem/capa/testing/__init__.py @@ -0,0 +1,7 @@ +""" +Reusable capa testing utilities. + +Unlike ``xblocks_contrib.problem.capa.tests``, this package ships in the +published distribution: it holds the fixtures that downstream test suites -- +notably openedx-platform's -- import. Keep actual tests out of it. +""" diff --git a/xblocks_contrib/problem/capa/testing/codejail.py b/xblocks_contrib/problem/capa/testing/codejail.py new file mode 100644 index 00000000..12e29bba --- /dev/null +++ b/xblocks_contrib/problem/capa/testing/codejail.py @@ -0,0 +1,31 @@ +"""Codejail controls for tests that execute capa problem code.""" + +import codejail.safe_exec +from django.test.utils import TestContextDecorator + + +class UseUnsafeCodejail(TestContextDecorator): + """ + Tell codejail to run in unsafe mode for the scope of the decorator. + Use this as a decorator on Django TestCase classes or methods. + + This is needed because codejail has significant OS-level setup requirements + which we don't even attempt to fulfill for unit testing purposes. Running + tests in unsafe mode (that is, running code executions in-process, with no + sandboxing) is only safe because we control the contents of the unit tests. + It's not a perfect replica of how safe mode operates but it's generally good + enough for testing the integration and overall behavior. + """ + + def __init__(self): + self.old_be_unsafe = None + super().__init__() + + def enable(self): + """Enable unsafe mode for codejail within the test scope.""" + self.old_be_unsafe = codejail.safe_exec.ALWAYS_BE_UNSAFE + codejail.safe_exec.ALWAYS_BE_UNSAFE = True + + def disable(self): + """Restore the previous codejail unsafe mode state.""" + codejail.safe_exec.ALWAYS_BE_UNSAFE = self.old_be_unsafe diff --git a/xblocks_contrib/problem/capa/tests/response_xml_factory.py b/xblocks_contrib/problem/capa/testing/response_xml_factory.py similarity index 100% rename from xblocks_contrib/problem/capa/tests/response_xml_factory.py rename to xblocks_contrib/problem/capa/testing/response_xml_factory.py diff --git a/xblocks_contrib/problem/capa/tests/test_capa_problem.py b/xblocks_contrib/problem/capa/tests/test_capa_problem.py index 4b449c7f..471da6b7 100644 --- a/xblocks_contrib/problem/capa/tests/test_capa_problem.py +++ b/xblocks_contrib/problem/capa/tests/test_capa_problem.py @@ -13,8 +13,8 @@ from xblocks_contrib.problem.capa.correctmap import CorrectMap from xblocks_contrib.problem.capa.responsetypes import LoncapaProblemError +from xblocks_contrib.problem.capa.testing.codejail import UseUnsafeCodejail from xblocks_contrib.problem.capa.tests.helpers import new_loncapa_problem -from xblocks_contrib.problem.capa.tests.test_util import UseUnsafeCodejail from xblocks_contrib.problem.markup import HTML diff --git a/xblocks_contrib/problem/capa/tests/test_html_render.py b/xblocks_contrib/problem/capa/tests/test_html_render.py index a94a1c45..df3b72fd 100644 --- a/xblocks_contrib/problem/capa/tests/test_html_render.py +++ b/xblocks_contrib/problem/capa/tests/test_html_render.py @@ -10,11 +10,11 @@ import ddt from lxml import etree +from xblocks_contrib.problem.capa.testing.codejail import UseUnsafeCodejail from xblocks_contrib.problem.capa.tests.helpers import mock_capa_system, new_loncapa_problem -from xblocks_contrib.problem.capa.tests.test_util import UseUnsafeCodejail from xblocks_contrib.problem.markup import HTML -from .response_xml_factory import CustomResponseXMLFactory, StringResponseXMLFactory +from ..testing.response_xml_factory import CustomResponseXMLFactory, StringResponseXMLFactory @ddt.ddt diff --git a/xblocks_contrib/problem/capa/tests/test_responsetypes.py b/xblocks_contrib/problem/capa/tests/test_responsetypes.py index ebe56052..5f0ee1cb 100644 --- a/xblocks_contrib/problem/capa/tests/test_responsetypes.py +++ b/xblocks_contrib/problem/capa/tests/test_responsetypes.py @@ -21,8 +21,8 @@ from xblocks_contrib.problem.capa.correctmap import CorrectMap from xblocks_contrib.problem.capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError -from xblocks_contrib.problem.capa.tests.helpers import load_fixture, mock_capa_system, new_loncapa_problem -from xblocks_contrib.problem.capa.tests.response_xml_factory import ( +from xblocks_contrib.problem.capa.testing.codejail import UseUnsafeCodejail +from xblocks_contrib.problem.capa.testing.response_xml_factory import ( AnnotationResponseXMLFactory, ChoiceResponseXMLFactory, ChoiceTextResponseXMLFactory, @@ -38,7 +38,7 @@ SymbolicResponseXMLFactory, TrueFalseResponseXMLFactory, ) -from xblocks_contrib.problem.capa.tests.test_util import UseUnsafeCodejail +from xblocks_contrib.problem.capa.tests.helpers import load_fixture, mock_capa_system, new_loncapa_problem from xblocks_contrib.problem.capa.util import convert_files_to_filenames from xblocks_contrib.problem.capa.xqueue_interface import DATEFORMAT diff --git a/xblocks_contrib/problem/capa/tests/test_util.py b/xblocks_contrib/problem/capa/tests/test_util.py index 683a0e0a..6e9ee901 100644 --- a/xblocks_contrib/problem/capa/tests/test_util.py +++ b/xblocks_contrib/problem/capa/tests/test_util.py @@ -4,9 +4,7 @@ import unittest -import codejail.safe_exec import ddt -from django.test.utils import TestContextDecorator from lxml import etree from xblocks_contrib.problem.capa.tests.helpers import mock_capa_system @@ -167,30 +165,3 @@ def test_contextualize_text_with_non_ascii_context(self): expected_text = "$あなたあなたあなたあなた あなたhi" contextual_text = contextualize_text(text, context) assert expected_text == contextual_text - - -class UseUnsafeCodejail(TestContextDecorator): - """ - Tell codejail to run in unsafe mode for the scope of the decorator. - Use this as a decorator on Django TestCase classes or methods. - - This is needed because codejail has significant OS-level setup requirements - which we don't even attempt to fulfill for unit testing purposes. Running - tests in unsafe mode (that is, running code executions in-process, with no - sandboxing) is only safe because we control the contents of the unit tests. - It's not a perfect replica of how safe mode operates but it's generally good - enough for testing the integration and overall behavior. - """ - - def __init__(self): - self.old_be_unsafe = None - super().__init__() - - def enable(self): - """Enable unsafe mode for codejail within the test scope.""" - self.old_be_unsafe = codejail.safe_exec.ALWAYS_BE_UNSAFE - codejail.safe_exec.ALWAYS_BE_UNSAFE = True - - def disable(self): - """Restore the previous codejail unsafe mode state.""" - codejail.safe_exec.ALWAYS_BE_UNSAFE = self.old_be_unsafe diff --git a/xblocks_contrib/problem/tests/test_capa_block.py b/xblocks_contrib/problem/tests/test_capa_block.py index 1af4f92a..0220683d 100644 --- a/xblocks_contrib/problem/tests/test_capa_block.py +++ b/xblocks_contrib/problem/tests/test_capa_block.py @@ -31,7 +31,7 @@ from xblocks_contrib.problem.capa import responsetypes from xblocks_contrib.problem.capa.correctmap import CorrectMap from xblocks_contrib.problem.capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError -from xblocks_contrib.problem.capa.tests.test_util import UseUnsafeCodejail +from xblocks_contrib.problem.capa.testing.codejail import UseUnsafeCodejail from xblocks_contrib.problem.capa.xqueue_interface import XQueueInterface from xblocks_contrib.problem.capa_block import ComplexEncoder, ProblemBlock from xblocks_contrib.problem.tests import DATA_DIR