From 52584249d25949795f2d13c7cc2fe86babf67a5e Mon Sep 17 00:00:00 2001 From: salmannawaz Date: Fri, 20 Oct 2023 14:05:22 +0500 Subject: [PATCH] Remove bok-choy usage (#322) * chore: remove bok-choy usage --- .github/workflows/ci.yml | 11 +-- requirements/base.txt | 6 +- requirements/dev.txt | 31 +------ requirements/pip.txt | 2 +- requirements/quality.txt | 29 ++----- requirements/test.in | 2 - requirements/test.txt | 22 +---- tox.ini | 1 - workbench/test/selenium_test.py | 39 --------- workbench/test/test_filethumbs.py | 78 ------------------ workbench/test/test_problems.py | 95 --------------------- workbench/test/test_thumbs.py | 133 ------------------------------ 12 files changed, 18 insertions(+), 431 deletions(-) delete mode 100644 workbench/test/selenium_test.py delete mode 100644 workbench/test/test_filethumbs.py delete mode 100644 workbench/test/test_problems.py delete mode 100644 workbench/test/test_thumbs.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c3a6939..cac933d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,22 +22,13 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: Set up test environment - run: | - sudo apt-get install xvfb - wget https://github.com/mozilla/geckodriver/releases/download/v0.15.0/geckodriver-v0.15.0-linux64.tar.gz - mkdir geckodriver - tar -xzf geckodriver-v0.15.0-linux64.tar.gz -C geckodriver - export PATH=$PATH:$(pwd)/geckodriver - export BOTO_CONFIG=/dev/null - - name: Install Requirements run: | pip install -r requirements/pip.txt pip install -r requirements/ci.txt - name: Run Tests - run: xvfb-run --server-args=-ac -- tox -e ${{ matrix.toxenv }} + run: tox -e ${{ matrix.toxenv }} - name: Upload coverage to CodeCov if: matrix.python-version == '3.8' && matrix.toxenv == 'django42' diff --git a/requirements/base.txt b/requirements/base.txt index dd1fb37d..b4bf1c00 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -12,9 +12,9 @@ asgiref==3.7.2 # via django binaryornot==0.4.4 # via cookiecutter -boto3==1.28.63 +boto3==1.28.65 # via fs-s3fs -botocore==1.31.63 +botocore==1.31.65 # via # boto3 # s3transfer @@ -115,7 +115,7 @@ typing-extensions==4.8.0 # via # asgiref # rich -urllib3==1.26.17 +urllib3==1.26.18 # via # botocore # requests diff --git a/requirements/dev.txt b/requirements/dev.txt index 22a3b67b..e419e9e3 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -32,16 +32,12 @@ binaryornot==0.4.4 # -r requirements/base.txt # -r requirements/test.txt # cookiecutter -bok-choy==0.7.1 - # via - # -r requirements/test.in - # -r requirements/test.txt -boto3==1.28.63 +boto3==1.28.65 # via # -r requirements/base.txt # -r requirements/test.txt # fs-s3fs -botocore==1.31.63 +botocore==1.31.65 # via # -r requirements/base.txt # -r requirements/test.txt @@ -152,7 +148,6 @@ lazy==1.6 # -r requirements/base.txt # -r requirements/test.txt # acid-xblock - # bok-choy # xblock lazy-object-proxy==1.9.0 # via astroid @@ -190,14 +185,6 @@ mock==5.1.0 # via # -r requirements/test.in # -r requirements/test.txt -needle==0.5.0 - # via - # -r requirements/test.txt - # bok-choy -nose==1.3.7 - # via - # -r requirements/test.txt - # needle openedx-django-pyfs==3.4.0 # via # -r requirements/base.txt @@ -211,10 +198,6 @@ packaging==23.2 # tox pbr==5.11.1 # via stevedore -pillow==10.0.1 - # via - # -r requirements/test.txt - # needle platformdirs==3.11.0 # via # -r requirements/test.txt @@ -315,12 +298,6 @@ s3transfer==0.7.0 # -r requirements/base.txt # -r requirements/test.txt # boto3 -selenium==3.4.1 - # via - # -r requirements/test.in - # -r requirements/test.txt - # bok-choy - # needle simplejson==3.19.2 # via # -r requirements/base.txt @@ -330,7 +307,6 @@ six==1.16.0 # via # -r requirements/base.txt # -r requirements/test.txt - # bok-choy # edx-lint # fs # fs-s3fs @@ -382,7 +358,7 @@ typing-extensions==4.8.0 # astroid # pylint # rich -urllib3==1.26.17 +urllib3==1.26.18 # via # -r requirements/base.txt # -r requirements/test.txt @@ -409,6 +385,7 @@ xblock[django]==1.8.1 # -r requirements/base.txt # -r requirements/test.txt # acid-xblock + # xblock # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/requirements/pip.txt b/requirements/pip.txt index 3e7d8f4a..2154d29f 100644 --- a/requirements/pip.txt +++ b/requirements/pip.txt @@ -8,7 +8,7 @@ wheel==0.41.2 # via -r requirements/pip.in # The following packages are considered to be unsafe in a requirements file: -pip==23.2.1 +pip==23.3 # via -r requirements/pip.in setuptools==68.2.2 # via -r requirements/pip.in diff --git a/requirements/quality.txt b/requirements/quality.txt index 2351b135..08ca462c 100644 --- a/requirements/quality.txt +++ b/requirements/quality.txt @@ -26,13 +26,11 @@ binaryornot==0.4.4 # via # -r requirements/test.txt # cookiecutter -bok-choy==0.7.1 - # via -r requirements/test.txt -boto3==1.28.63 +boto3==1.28.65 # via # -r requirements/test.txt # fs-s3fs -botocore==1.31.63 +botocore==1.31.65 # via # -r requirements/test.txt # boto3 @@ -65,6 +63,7 @@ cookiecutter==2.4.0 coverage[toml]==7.3.2 # via # -r requirements/test.txt + # coverage # pytest-cov ddt==1.6.0 # via -r requirements/test.txt @@ -126,7 +125,6 @@ lazy==1.6 # via # -r requirements/test.txt # acid-xblock - # bok-choy # xblock lazy-object-proxy==1.9.0 # via astroid @@ -157,14 +155,6 @@ mdurl==0.1.2 # markdown-it-py mock==5.1.0 # via -r requirements/test.txt -needle==0.5.0 - # via - # -r requirements/test.txt - # bok-choy -nose==1.3.7 - # via - # -r requirements/test.txt - # needle openedx-django-pyfs==3.4.0 # via # -r requirements/test.txt @@ -177,10 +167,6 @@ packaging==23.2 # tox pbr==5.11.1 # via stevedore -pillow==10.0.1 - # via - # -r requirements/test.txt - # needle platformdirs==3.11.0 # via # -r requirements/test.txt @@ -265,11 +251,6 @@ s3transfer==0.7.0 # via # -r requirements/test.txt # boto3 -selenium==3.4.1 - # via - # -r requirements/test.txt - # bok-choy - # needle simplejson==3.19.2 # via # -r requirements/test.txt @@ -277,7 +258,6 @@ simplejson==3.19.2 six==1.16.0 # via # -r requirements/test.txt - # bok-choy # edx-lint # fs # fs-s3fs @@ -322,7 +302,7 @@ typing-extensions==4.8.0 # astroid # pylint # rich -urllib3==1.26.17 +urllib3==1.26.18 # via # -r requirements/test.txt # botocore @@ -345,6 +325,7 @@ xblock[django]==1.8.1 # via # -r requirements/test.txt # acid-xblock + # xblock # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/requirements/test.in b/requirements/test.in index 1cef2888..5f9513ca 100644 --- a/requirements/test.in +++ b/requirements/test.in @@ -2,13 +2,11 @@ -r base.txt acid-xblock -bok_choy==0.7.1 coverage ddt mock pytest-django pytest-cov pytest-rerunfailures -selenium==3.4.1 # Forcing this version fixes issues on CI tox # Virtualenv management for tests tox-battery # Makes tox aware of requirements file changes diff --git a/requirements/test.txt b/requirements/test.txt index 1e7237d8..cf3641c7 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -22,13 +22,11 @@ binaryornot==0.4.4 # via # -r requirements/base.txt # cookiecutter -bok-choy==0.7.1 - # via -r requirements/test.in -boto3==1.28.63 +boto3==1.28.65 # via # -r requirements/base.txt # fs-s3fs -botocore==1.31.63 +botocore==1.31.65 # via # -r requirements/base.txt # boto3 @@ -98,7 +96,6 @@ lazy==1.6 # via # -r requirements/base.txt # acid-xblock - # bok-choy # xblock lxml==4.9.3 # via @@ -125,10 +122,6 @@ mdurl==0.1.2 # markdown-it-py mock==5.1.0 # via -r requirements/test.in -needle==0.5.0 - # via bok-choy -nose==1.3.7 - # via needle openedx-django-pyfs==3.4.0 # via # -r requirements/base.txt @@ -138,8 +131,6 @@ packaging==23.2 # pytest # pytest-rerunfailures # tox -pillow==10.0.1 - # via needle platformdirs==3.11.0 # via virtualenv pluggy==1.3.0 @@ -197,11 +188,6 @@ s3transfer==0.7.0 # via # -r requirements/base.txt # boto3 -selenium==3.4.1 - # via - # -r requirements/test.in - # bok-choy - # needle simplejson==3.19.2 # via # -r requirements/base.txt @@ -209,7 +195,6 @@ simplejson==3.19.2 six==1.16.0 # via # -r requirements/base.txt - # bok-choy # fs # fs-s3fs # python-dateutil @@ -243,7 +228,7 @@ typing-extensions==4.8.0 # -r requirements/base.txt # asgiref # rich -urllib3==1.26.17 +urllib3==1.26.18 # via # -r requirements/base.txt # botocore @@ -262,6 +247,7 @@ xblock[django]==1.8.1 # via # -r requirements/base.txt # acid-xblock + # xblock # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/tox.ini b/tox.ini index 2e1671f7..602aa549 100644 --- a/tox.ini +++ b/tox.ini @@ -19,7 +19,6 @@ deps = -r{toxinidir}/requirements/test.txt passenv = DISPLAY - BOTO_CONFIG commands = make var/workbench.db python -Wd -m pytest {posargs} diff --git a/workbench/test/selenium_test.py b/workbench/test/selenium_test.py deleted file mode 100644 index c5f3b964..00000000 --- a/workbench/test/selenium_test.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -Helpers for Selenium tests. -""" - - - -import pytest -from bok_choy.web_app_test import WebAppTest -from selenium.webdriver.support.expected_conditions import staleness_of -from selenium.webdriver.support.ui import WebDriverWait - -from django.contrib.staticfiles.testing import StaticLiveServerTestCase - -from workbench.runtime_util import reset_global_state - - -@pytest.mark.selenium -class SeleniumTest(WebAppTest, StaticLiveServerTestCase): - """ - Base test class that provides setUpClass and tearDownClass - methods necessary for selenium testing. - """ - - def setUp(self): - super().setUp() - - # Clear the in-memory key value store, the usage store, and whatever - # else needs to be cleared and re-initialized. - reset_global_state() - - def wait_for_page_load(self, old_element, timeout=30): - """ - Uses Selenium's built-in "staleness" hook to wait until the page has - loaded. For use when clicking a link to ensure that the new page - has loaded before selecting elements. I think that this could be used - to check that elements have been made stale via ajax as well, but it - is not being used for that in any of the tests here. - """ - return WebDriverWait(self.browser, timeout).until(staleness_of(old_element)) diff --git a/workbench/test/test_filethumbs.py b/workbench/test/test_filethumbs.py deleted file mode 100644 index 4b661f77..00000000 --- a/workbench/test/test_filethumbs.py +++ /dev/null @@ -1,78 +0,0 @@ -"""Tests for the thumbs module""" - - -import pytest -from bok_choy.promise import EmptyPromise - -from workbench import scenarios -from workbench.test.selenium_test import SeleniumTest - - -class ThreeThumbsTest(SeleniumTest): - """Test the functionalities of the three thumbs test XBlock.""" - - def setUp(self): - super().setUp() - - scenarios.add_xml_scenario( - "test_three_file_thumbs", "three file thumbs test", - """""" - ) - self.addCleanup(scenarios.remove_scenario, "test_three_file_thumbs") - - # Suzy opens the browser to visit the workbench - self.browser.get(self.live_server_url) - - # She knows it's the site by the header - header1 = self.browser.find_element_by_css_selector('h1') - self.assertEqual(header1.text, 'XBlock scenarios') - - @pytest.mark.flaky(reruns=5, reruns_delay=2) - def test_three_thumbs_initial_state(self): - # She clicks on the three thumbs at once scenario - link = self.browser.find_element_by_link_text('three file thumbs test') - link.click() - self.wait_for_page_load(link, timeout=10) - - # The header reflects the XBlock - header1 = self.browser.find_element_by_css_selector('h1') - self.assertEqual(header1.text, 'XBlock: three file thumbs test') - - # She sees that there are 3 sets of thumbs - vertical_css = 'div.student_view > div.xblock-v1 > div.vertical' - - # The following will give a NoSuchElementException error - # if it is not there - vertical = self.browser.find_element_by_css_selector(vertical_css) - - # Make sure there are three thumbs blocks - thumb_css = 'div.xblock-v1[data-block-type="filethumbs"]' - thumbs = vertical.find_elements_by_css_selector(thumb_css) - self.assertEqual(3, len(thumbs)) - - # Make sure they all have 0 for upvote and downvote counts - up_count_css = 'span.upvote span.count' - down_count_css = 'span.downvote span.count' - - for thumb in thumbs: - # pylint: disable=cell-var-from-loop - up_count = thumb.find_element_by_css_selector(up_count_css) - down_count = thumb.find_element_by_css_selector(down_count_css) - initial_up = int(up_count.text) - initial_down = int(down_count.text) - - # upvote - thumb.find_element_by_css_selector('span.upvote').click() - _ = EmptyPromise( - lambda: int(thumb.find_element_by_css_selector(up_count_css).text) == initial_up + 1, - "upvote action succeeded" - ).fulfill() - self.assertEqual(initial_down, int(thumb.find_element_by_css_selector(down_count_css).text)) - - # downvote - thumb.find_element_by_css_selector('span.downvote').click() - _ = EmptyPromise( - lambda: int(thumb.find_element_by_css_selector(down_count_css).text) == initial_down + 1, - "downvote action succeeded" - ).fulfill() - self.assertEqual(initial_up + 1, int(thumb.find_element_by_css_selector(up_count_css).text)) diff --git a/workbench/test/test_problems.py b/workbench/test/test_problems.py deleted file mode 100644 index 3fb1954a..00000000 --- a/workbench/test/test_problems.py +++ /dev/null @@ -1,95 +0,0 @@ -"""Test that problems and problem submission works well.""" - - -import time -import unittest - -from bok_choy.query import BrowserQuery -from selenium.common.exceptions import StaleElementReferenceException - -from workbench import scenarios -from workbench.test.selenium_test import SeleniumTest - - -class ProblemInteractionTest(SeleniumTest): - """ - A browser-based test of answering problems right and wrong. - """ - - def setUp(self): - super().setUp() - - one_problem = """ - -

$a $b

- - - -
- """ - self.num_problems = 3 - scenarios.add_xml_scenario( - "test_many_problems", "Many problems", - "" + one_problem * self.num_problems + "" - ) - self.addCleanup(scenarios.remove_scenario, "test_many_problems") - - @unittest.skip("Flaky test: PLAT-614") - def test_many_problems(self): - # Test that problems work properly. - self.browser.get(self.live_server_url + "/scenario/test_many_problems") - header1 = BrowserQuery(self.browser, css="h1") - self.assertEqual(header1.text[0], "XBlock: Many problems") - - # Find the numbers on the page. - nums = self.browser.find_elements_by_css_selector("p.the_numbers") - num_pairs = [tuple(int(n) for n in num.text.split()) for num in nums] - - # They should be all different. - self.assertEqual(len(set(num_pairs)), self.num_problems) - - text_ctrls_xpath = '//div[@data-block-type="textinput_demo"][@data-name="sum_input"]/input' - text_ctrls = self.browser.find_elements_by_xpath(text_ctrls_xpath) - check_btns = BrowserQuery(self.browser, css='input.check') - check_indicators = 'span.indicator' - - def assert_image(right_wrong_idx, expected_icon): - """Assert that the img src text includes `expected_icon`""" - for _ in range(3): - try: - sources = BrowserQuery( - self.browser, - css='{} img'.format( - check_indicators, - ), - ).nth(right_wrong_idx).attrs('src') - if sources and expected_icon in sources[0]: - break - time.sleep(.25) - except StaleElementReferenceException as exc: - print(exc) - self.assertIn(expected_icon, sources[0]) - - for i in range(self.num_problems): - # Before answering, the indicator says Not Attempted. - self.assertIn("Not attempted", BrowserQuery(self.browser, css=check_indicators).nth(i).text[0]) - - answer = sum(num_pairs[i]) - - for _ in range(2): - # Answer right. - text_ctrls[i].clear() - text_ctrls[i].send_keys(str(answer)) - check_btns[i].click() - assert_image(i, "/correct-icon.png") - - # Answer wrong. - text_ctrls[i].clear() - text_ctrls[i].send_keys(str(answer + 1)) - check_btns[i].click() - assert_image(i, "/incorrect-icon.png") diff --git a/workbench/test/test_thumbs.py b/workbench/test/test_thumbs.py deleted file mode 100644 index a70da453..00000000 --- a/workbench/test/test_thumbs.py +++ /dev/null @@ -1,133 +0,0 @@ -"""Tests for the thumbs module""" - - -import pytest -from bok_choy.promise import EmptyPromise - -from workbench import scenarios -from workbench.test.selenium_test import SeleniumTest - -pytestmark = pytest.mark.django_db - - -class ThreeThumbsTest(SeleniumTest): - """Test the functionalities of the three thumbs test XBlock.""" - - def setUp(self): - super().setUp() - - scenarios.add_xml_scenario( - "test_three_thumbs", "three thumbs test", - """""" - ) - self.addCleanup(scenarios.remove_scenario, "test_three_thumbs") - - # Suzy opens the browser to visit the workbench - self.browser.get(self.live_server_url) - - # She knows it's the site by the header - header1 = self.browser.find_element_by_css_selector('h1') - self.assertEqual(header1.text, 'XBlock scenarios') - - @pytest.mark.flaky(reruns=5, reruns_delay=2) - def test_three_thumbs_initial_state(self): - # She clicks on the three thumbs at once scenario - link = self.browser.find_element_by_link_text('three thumbs test') - link.click() - self.wait_for_page_load(link, timeout=10) - - # The header reflects the XBlock - header1 = self.browser.find_element_by_css_selector('h1') - self.assertEqual(header1.text, 'XBlock: three thumbs test') - - # She sees that there are 3 sets of thumbs - vertical_css = 'div.student_view > div.xblock-v1 > div.vertical' - - # The following will give a NoSuchElementException error - # if it is not there - vertical = self.browser.find_element_by_css_selector(vertical_css) - - # Make sure there are three thumbs blocks - thumb_css = 'div.xblock-v1[data-block-type="thumbs"]' - thumbs = vertical.find_elements_by_css_selector(thumb_css) - self.assertEqual(3, len(thumbs)) - - # Make sure they all have 0 for upvote and downvote counts - up_count_css = 'span.upvote span.count' - down_count_css = 'span.downvote span.count' - - for thumb in thumbs: - up_count = thumb.find_element_by_css_selector(up_count_css) - down_count = thumb.find_element_by_css_selector(down_count_css) - self.assertEqual('0', up_count.text) - self.assertEqual('0', down_count.text) - - @pytest.mark.flaky(reruns=5, reruns_delay=2) - def test_three_upvoting(self): - # She clicks on the three thumbs at once scenario - link = self.browser.find_element_by_link_text('three thumbs test') - link.click() - self.wait_for_page_load(link, timeout=10) - - # The vertical that contains the thumbs - vertical_css = 'div.student_view > div.xblock-v1 > div.vertical' - vertical = self.browser.find_element_by_css_selector(vertical_css) - - # The three thumbs blocks - thumb_css = 'div.xblock-v1[data-block-type="thumbs"]' - thumbs = vertical.find_elements_by_css_selector(thumb_css) - - # Up and down counts - up_count_css = 'span.upvote span.count' - down_count_css = 'span.downvote span.count' - - # Up vote for the first thumb - thumbs[0].find_element_by_css_selector('span.upvote').click() - - # Only the first thumb's upcount should increase - _ = EmptyPromise( - lambda: int(thumbs[0].find_element_by_css_selector(up_count_css).text) == 1, - "upvote action succeeded" - ).fulfill() - self.assertEqual('0', thumbs[1].find_element_by_css_selector(up_count_css).text) - self.assertEqual('0', thumbs[2].find_element_by_css_selector(up_count_css).text) - - # Down counts should all still be zero - for thumb in thumbs: - down_count = thumb.find_element_by_css_selector(down_count_css) - self.assertEqual('0', down_count.text) - - @pytest.mark.flaky(reruns=5, reruns_delay=2) - def test_three_downvoting(self): - # She clicks on the three thumbs at once scenario - link = self.browser.find_element_by_link_text('three thumbs test') - link.click() - self.wait_for_page_load(link, timeout=10) - - # The vertical that contains the thumbs - vertical_css = 'div.student_view > div.xblock-v1 > div.vertical' - vertical = self.browser.find_element_by_css_selector(vertical_css) - - # The three thumbs blocks - thumb_css = 'div.xblock-v1[data-block-type="thumbs"]' - thumbs = vertical.find_elements_by_css_selector(thumb_css) - - # Up and down counts - up_count_css = 'span.upvote span.count' - down_count_css = 'span.downvote span.count' - - # Up vote for the first thumb - thumbs[0].find_element_by_css_selector('span.downvote').click() - - # Only the first thumb's downcount should increase - _ = EmptyPromise( - lambda: int(thumbs[0].find_element_by_css_selector(down_count_css).text) == 1, - "downvote action succeeded" - ).fulfill() - self.assertEqual('0', thumbs[1].find_element_by_css_selector(down_count_css).text) - self.assertEqual('0', thumbs[2].find_element_by_css_selector(down_count_css).text) - - # Up counts should all still be zero - for thumb in thumbs: - down_count = thumb.find_element_by_css_selector(up_count_css) - self.assertEqual('0', down_count.text)