diff --git a/.github/workflows/unit-test-shards.json b/.github/workflows/unit-test-shards.json index 50e54ea22402..d224cc22b90f 100644 --- a/.github/workflows/unit-test-shards.json +++ b/.github/workflows/unit-test-shards.json @@ -78,7 +78,7 @@ "lms/tests.py" ] }, - "openedx-1": { + "openedx-1-with-lms": { "settings": "lms.envs.test", "paths": [ "openedx/core/djangoapps/ace_common/", @@ -116,7 +116,7 @@ "openedx/core/djangoapps/external_user_ids/" ] }, - "openedx-2": { + "openedx-2-with-lms": { "settings": "lms.envs.test", "paths": [ "openedx/core/djangoapps/geoinfo/", @@ -159,7 +159,7 @@ "openedx/tests/" ] }, - "openedx-3": { + "openedx-1-with-cms": { "settings": "cms.envs.test", "paths": [ "openedx/core/djangoapps/ace_common/", @@ -197,7 +197,7 @@ "openedx/core/djangoapps/external_user_ids/" ] }, - "openedx-4": { + "openedx-2-with-cms": { "settings": "cms.envs.test", "paths": [ "openedx/core/djangoapps/content_tagging/", @@ -258,22 +258,28 @@ "cms/djangoapps/contentstore/" ] }, - "common-1": { + "common-with-lms": { "settings": "lms.envs.test", "paths": [ "common/djangoapps/" ] }, - "common-2": { + "common-with-cms": { "settings": "cms.envs.test", "paths": [ "common/djangoapps/" ] }, - "xmodule-1": { + "xmodule-with-lms": { "settings": "lms.envs.test", "paths": [ "xmodule/" ] + }, + "xmodule-with-cms": { + "settings": "cms.envs.test", + "paths": [ + "xmodule/" + ] } } diff --git a/.github/workflows/unit-tests-gh-hosted.yml b/.github/workflows/unit-tests-gh-hosted.yml index 5062df625c3a..60dabbbecec8 100644 --- a/.github/workflows/unit-tests-gh-hosted.yml +++ b/.github/workflows/unit-tests-gh-hosted.yml @@ -26,15 +26,16 @@ jobs: - "lms-4" - "lms-5" - "lms-6" - - "openedx-1" - - "openedx-2" - - "openedx-3" - - "openedx-4" + - "openedx-1-with-lms" + - "openedx-2-with-lms" + - "openedx-1-with-cms" + - "openedx-2-with-cms" - "cms-1" - "cms-2" - - "common-1" - - "common-2" - - "xmodule-1" + - "common-with-lms" + - "common-with-cms" + - "xmodule-with-lms" + - "xmodule-with-cms" name: gh-hosted-python-${{ matrix.python-version }},django-${{ matrix.django-version }},${{ matrix.shard_name }} steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 230fe9bec5df..c3b1086c20eb 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -27,15 +27,16 @@ jobs: - "lms-4" - "lms-5" - "lms-6" - - "openedx-1" - - "openedx-2" - - "openedx-3" - - "openedx-4" + - "openedx-1-with-lms" + - "openedx-2-with-lms" + - "openedx-1-with-cms" + - "openedx-2-with-cms" - "cms-1" - "cms-2" - - "common-1" - - "common-2" - - "xmodule-1" + - "common-with-lms" + - "common-with-cms" + - "xmodule-with-lms" + - "xmodule-with-cms" # We expect Django 4.0 to fail, so don't stop when it fails. continue-on-error: ${{ matrix.django-version == '4.0' }} diff --git a/xmodule/capa/safe_exec/tests/test_safe_exec.py b/xmodule/capa/safe_exec/tests/test_safe_exec.py index 0f6429ec5e06..fa12e4f69903 100644 --- a/xmodule/capa/safe_exec/tests/test_safe_exec.py +++ b/xmodule/capa/safe_exec/tests/test_safe_exec.py @@ -18,6 +18,7 @@ from six import unichr from six.moves import range +from openedx.core.djangolib.testing.utils import skip_unless_lms from xmodule.capa.safe_exec import safe_exec, update_hash from xmodule.capa.safe_exec.remote_exec import is_codejail_rest_service_enabled @@ -81,17 +82,30 @@ def test_raising_exceptions(self): class TestSafeOrNot(unittest.TestCase): # lint-amnesty, pylint: disable=missing-class-docstring + + @skip_unless_lms def test_cant_do_something_forbidden(self): ''' Demonstrates that running unsafe code inside the code jail throws SafeExecException, protecting the calling process. + + This test generally is skipped in CI due to its complex setup. That said, we recommend that devs who are + hacking on CodeJail or advanced CAPA in any significant way take the time to make sure it passes locally. + See either: + * in-platform setup: https://github.com/openedx/edx-platform/blob/master/xmodule/capa/safe_exec/README.rst + * remote setup (using Tutor): https://github.com/eduNEXT/tutor-contrib-codejail + + Note on @skip_unless_lms: + This test can also be run in a CMS context, but that's giving us trouble in CI right now (the skip logic isn't + working). So, if you're running this locally, feel free to remove @skip_unless_lms and run it against CMS too. ''' - # Can't test for forbiddenness if CodeJail isn't configured for python. + # If in-platform codejail isn't configured... if not jail_code.is_configured("python"): - # Can't test for forbiddenness if CodeJail rest service isn't enabled. - # Remote codejailservice must be running, see https://github.com/eduNEXT/tutor-contrib-codejail/ + # ...AND if remote codejail isn't configured... if not is_codejail_rest_service_enabled(): + + # ...then skip this test. pytest.skip(reason="Local or remote codejail has to be configured and enabled to run this test.") g = {} diff --git a/xmodule/capa/tests/test_xqueue_interface.py b/xmodule/capa/tests/test_xqueue_interface.py index 5fd913a15ec1..819fd73c798b 100644 --- a/xmodule/capa/tests/test_xqueue_interface.py +++ b/xmodule/capa/tests/test_xqueue_interface.py @@ -8,9 +8,11 @@ from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator from xblock.fields import ScopeIds +from openedx.core.djangolib.testing.utils import skip_unless_lms from xmodule.capa.xqueue_interface import XQueueInterface, XQueueService +@skip_unless_lms class XQueueServiceTest(TestCase): """Test the XQueue service methods.""" def setUp(self): diff --git a/xmodule/tests/test_capa_block.py b/xmodule/tests/test_capa_block.py index b511fe403e43..ab94028fc955 100644 --- a/xmodule/tests/test_capa_block.py +++ b/xmodule/tests/test_capa_block.py @@ -29,6 +29,7 @@ from xblock.scorable import Score import xmodule +from openedx.core.djangolib.testing.utils import skip_unless_lms from xmodule.capa import responsetypes from xmodule.capa.correctmap import CorrectMap from xmodule.capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError @@ -182,6 +183,7 @@ class CapaFactoryWithFiles(CapaFactory): @ddt.ddt +@skip_unless_lms class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=missing-class-docstring def setUp(self): @@ -2898,6 +2900,7 @@ def test_default(self): # ignore quotes +@skip_unless_lms class ProblemCheckTrackingTest(unittest.TestCase): """ Ensure correct tracking information is included in events emitted during problem checks. diff --git a/xmodule/tests/test_library_tools.py b/xmodule/tests/test_library_tools.py index 950307b6963d..e2daa723cc7b 100644 --- a/xmodule/tests/test_library_tools.py +++ b/xmodule/tests/test_library_tools.py @@ -1,9 +1,10 @@ """ -Tests for library tools service. +Tests for library tools service (only used by CMS) """ from unittest.mock import patch from opaque_keys.edx.keys import UsageKey +from openedx.core.djangolib.testing.utils import skip_unless_cms from openedx.core.djangoapps.content_libraries import api as library_api from openedx.core.djangoapps.content_libraries.tests.base import ContentLibrariesRestApiTest from openedx.core.djangoapps.xblock.api import load_block @@ -13,6 +14,7 @@ from xmodule.modulestore.tests.utils import MixedSplitTestCase +@skip_unless_cms class LibraryToolsServiceTest(MixedSplitTestCase): """ Tests for library service. @@ -40,6 +42,7 @@ def test_list_available_libraries_fetch(self, mock_get_library_summaries): assert mock_get_library_summaries.called +@skip_unless_cms class ContentLibraryToolsTest(MixedSplitTestCase, ContentLibrariesRestApiTest): """ Tests for LibraryToolsService which interact with blockstore-based content libraries @@ -63,16 +66,16 @@ def test_import_from_blockstore(self): course = CourseFactory.create(modulestore=self.store, user_id=self.user.id) CourseInstructorRole(course.id).add_users(self.user) # Add Source from library block to the course - sourced_block = self.make_block("library_sourced", course, user_id=self.user.id) + lc_block = self.make_block("library_content", course, user_id=self.user.id) # Import the unit block from the library to the course - self.tools.import_from_blockstore(sourced_block, [unit_block_id]) + self.tools.import_from_blockstore(lc_block, [unit_block_id]) # Verify imported block with its children - assert len(sourced_block.children) == 1 - assert sourced_block.children[0].category == 'unit' + assert len(lc_block.children) == 1 + assert lc_block.children[0].category == 'unit' - imported_unit_block = self.store.get_item(sourced_block.children[0]) + imported_unit_block = self.store.get_item(lc_block.children[0]) assert len(imported_unit_block.children) == 1 assert imported_unit_block.children[0].category == 'html' @@ -86,10 +89,10 @@ def test_import_from_blockstore(self): # Check that reimporting updates the target block self._set_library_block_olx(html_block_id, 'Foo bar') - self.tools.import_from_blockstore(sourced_block, [unit_block_id]) + self.tools.import_from_blockstore(lc_block, [unit_block_id]) - assert len(sourced_block.children) == 1 - imported_unit_block = self.store.get_item(sourced_block.children[0]) + assert len(lc_block.children) == 1 + imported_unit_block = self.store.get_item(lc_block.children[0]) assert len(imported_unit_block.children) == 1 imported_html_block = self.store.get_item(imported_unit_block.children[0]) assert 'Hello world' not in imported_html_block.data