From 547815c95f59a7583c8ce685dbc9f55241813afa Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Mon, 14 Sep 2015 11:46:04 -0400 Subject: [PATCH 1/9] Upgrade to Django 1.8 --- Makefile | 7 +++++++ requirements/base.txt | 2 +- workbench/templates/workbench/block.html | 1 - workbench/templates/workbench/blockview.html | 2 -- workbench/templates/workbench/index.html | 1 - workbench/views.py | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index edd588bd..5388cd4d 100755 --- a/Makefile +++ b/Makefile @@ -36,3 +36,10 @@ quality: cover: coverage run manage.py test coverage report + +clean: + rm -f workbench.log* workbench.test.* + rm -rf workbench/static/djpyfs + rm -rf *.egg-info + rm -f .coverage + find . -name '.git' -prune -o -name '*.pyc' -exec rm {} \; diff --git a/requirements/base.txt b/requirements/base.txt index 553daac8..1cc6b3f3 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,5 +1,5 @@ cookiecutter==0.9.0 -Django >= 1.4, < 1.5 +Django==1.8.4 lxml requests webob diff --git a/workbench/templates/workbench/block.html b/workbench/templates/workbench/block.html index d209cbff..0406e0d3 100644 --- a/workbench/templates/workbench/block.html +++ b/workbench/templates/workbench/block.html @@ -1,6 +1,5 @@ {% load staticfiles %} -{% load url from future %} diff --git a/workbench/templates/workbench/index.html b/workbench/templates/workbench/index.html index 956a27d0..e128d216 100644 --- a/workbench/templates/workbench/index.html +++ b/workbench/templates/workbench/index.html @@ -1,5 +1,4 @@ {% load staticfiles %} -{% load url from future %} diff --git a/workbench/views.py b/workbench/views.py index e801fd2c..f07b6269 100644 --- a/workbench/views.py +++ b/workbench/views.py @@ -160,7 +160,7 @@ def package_resource(_request, block_type, resource): except Exception: # pylint: disable-msg=broad-except raise Http404 mimetype, _ = mimetypes.guess_type(resource) - return HttpResponse(content, mimetype=mimetype) + return HttpResponse(content, content_type=mimetype) @csrf_exempt From bff708f4ad9ce5f85e15a8afd7b391aacdad637e Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Mon, 14 Sep 2015 12:14:29 -0400 Subject: [PATCH 2/9] Modernize .travis.yml --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index 130bf4b5..4437b826 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,28 @@ sudo: false + language: python + python: - "2.7" + branches: only: - master cache: directories: - $HOME/.cache/pip + before_install: - "export DISPLAY=:99" - "sh -e /etc/init.d/xvfb start" + install: - "make install" - "pip install coveralls" + script: - "make quality" - "make cover" + after_success: - "coveralls" From 3bdb1015545173cb21437d0a0370e57f8875cce0 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Mon, 14 Sep 2015 16:46:20 -0400 Subject: [PATCH 3/9] Django 1.7 LiveServerTestCase doesn't serve static files. Use StaticLiveServerTestCase --- workbench/test/selenium_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/workbench/test/selenium_test.py b/workbench/test/selenium_test.py index ba0bb560..ad9246a8 100644 --- a/workbench/test/selenium_test.py +++ b/workbench/test/selenium_test.py @@ -1,6 +1,6 @@ """Helpers for Selenium tests.""" -from django.test import LiveServerTestCase +from django.contrib.staticfiles.testing import StaticLiveServerTestCase from bok_choy.web_app_test import WebAppTest from nose.plugins.attrib import attr @@ -9,7 +9,7 @@ @attr('selenium') -class SeleniumTest(WebAppTest, LiveServerTestCase): +class SeleniumTest(WebAppTest, StaticLiveServerTestCase): """Base test class that provides setUpClass and tearDownClass methods necessary for selenium testing.""" From 6b5b6e277a8a13264a9b385c3b943948eee67743 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Tue, 15 Sep 2015 12:41:21 -0400 Subject: [PATCH 4/9] Fix scenario tests to reset scenarios before the test In 1.7, Django changed from cleaning up before tests to cleaning up after tests. This borked the scenario tests. To fix it, they need a setup to reset the scenarios. Rather than continue to use the nose test generator feature, I've converted the test to be a classic unittest class-based test. The scenarios were being init'ed explicitly in a few places, but this also interfered with tests. Now importing the scenarios.py module inits the scenarios. A few other places that need explicit resetting still call init_scenarios. --- workbench/scenarios.py | 2 + workbench/test/test_scenarios.py | 110 +++++++++++++++++-------------- workbench/urls.py | 2 - 3 files changed, 61 insertions(+), 53 deletions(-) diff --git a/workbench/scenarios.py b/workbench/scenarios.py index 4537b959..b02b6e95 100644 --- a/workbench/scenarios.py +++ b/workbench/scenarios.py @@ -74,3 +74,5 @@ def init_scenarios(): # Get all the XBlock classes, and add their scenarios. for class_name, cls in sorted(XBlock.load_classes(fail_silently=False)): add_class_scenarios(class_name, cls, fail_silently=False) + +init_scenarios() diff --git a/workbench/test/test_scenarios.py b/workbench/test/test_scenarios.py index 71e33088..cd0a0354 100644 --- a/workbench/test/test_scenarios.py +++ b/workbench/test/test_scenarios.py @@ -1,60 +1,68 @@ """Test that all scenarios render successfully.""" -import lxml.html +import unittest +import ddt from django.test.client import Client +import lxml.html +from django.core.urlresolvers import reverse from xblock.test.tools import assert_equals + from workbench import scenarios +from workbench.runtime import reset_global_state + + +@ddt.ddt +class ScenarioTest(unittest.TestCase): + """Test the scenario support.""" + def setUp(self): + super(ScenarioTest, self).setUp() + reset_global_state() + + def test_all_scenarios(self): + """Load the home page, examine the scenarios displayed.""" + client = Client() + response = client.get("/") + assert response.status_code == 200 + html = lxml.html.fromstring(response.content) + a_tags = list(html.xpath('//a')) + + # Load the loaded_scenarios from the classes. + loaded_scenarios = scenarios.SCENARIOS.values() + + # We should have an tag for each scenario. + assert_equals(len(a_tags), len(loaded_scenarios)) + + # We should have at least one scenario with a vertical tag, since we use + # empty verticals as our canary in the coal mine that something has gone + # horribly wrong with loading the loaded_scenarios. + assert any("" in scen.xml for scen in loaded_scenarios) + + # Since we are claiming in try_scenario that no vertical is empty, let's + # eliminate the possibility that a scenario has an actual empty vertical. + assert all("" not in scen.xml for scen in loaded_scenarios) + assert all("" not in scen.xml for scen in loaded_scenarios) + + @ddt.data(*scenarios.SCENARIOS.keys()) + def test_scenario(self, scenario_id): + """A very shallow test, just to see if the scenario loads all its blocks. + + We don't know enough about each scenario to know what each should do. + So we load the scenario to see that the workbench could successfully + serve it. + """ + url = reverse('workbench_show_scenario', kwargs={'scenario_id': scenario_id}) + client = Client() + response = client.get(url, follow=True) + assert response.status_code == 200, name -def test_all_scenarios(): - """Load the home page, get every URL, make a test from it.""" - client = Client() - response = client.get("/") - assert response.status_code == 200 - html = lxml.html.fromstring(response.content) - a_tags = list(html.xpath('//a')) - for a_tag in a_tags: - yield try_scenario, a_tag.get('href'), a_tag.text - - # Load the loaded_scenarios from the classes. - loaded_scenarios = scenarios.SCENARIOS.values() - - # We should have an tag for each scenario. - assert_equals(len(a_tags), len(loaded_scenarios)) - - # We should have at least one scenario with a vertical tag, since we use - # empty verticals as our canary in the coal mine that something has gone - # horribly wrong with loading the loaded_scenarios. - assert any("" in scen.xml for scen in loaded_scenarios) - - # Since we are claiming in try_scenario that no vertical is empty, let's - # eliminate the possibility that a scenario has an actual empty vertical. - assert all("" not in scen.xml for scen in loaded_scenarios) - assert all("" not in scen.xml for scen in loaded_scenarios) - - -def try_scenario(url, name): - """Check that a scenario renders without error. - - `url`: the URL to the scenario to test. - - `name`: the name of the scenario, used in error messages. - - """ - # This is a very shallow test. We don't know enough about each scenario to - # know what each should do. So we load the scenario to see that the - # workbench could successfully serve it. - client = Client() - response = client.get(url, follow=True) - assert response.status_code == 200, name - - # Be sure we got the whole scenario. Again, we can't know what to expect - # here, but at the very least, if there are verticals, they should not be - # empty. That would be a sign that some data wasn't loaded properly while - # rendering the scenario. - html = lxml.html.fromstring(response.content) - for vertical_tag in html.xpath('//div[@class="vertical"]'): - # No vertical tag should be empty. - assert list(vertical_tag), "Empty shouldn't happen!" + # Be sure we got the whole scenario. Again, we can't know what to expect + # here, but at the very least, if there are verticals, they should not be + # empty. That would be a sign that some data wasn't loaded properly while + # rendering the scenario. + html = lxml.html.fromstring(response.content) + for vertical_tag in html.xpath('//div[@class="vertical"]'): + # No vertical tag should be empty. + assert list(vertical_tag), "Empty shouldn't happen!" diff --git a/workbench/urls.py b/workbench/urls.py index b3f88eee..2a28dd45 100644 --- a/workbench/urls.py +++ b/workbench/urls.py @@ -8,8 +8,6 @@ admin.autodiscover() -init_scenarios() - urlpatterns = patterns( 'workbench.views', url(r'^$', 'index', name='workbench_index'), From 4dc6f2718b9f44e64d40c98ff259a26baa124fd8 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Tue, 15 Sep 2015 17:23:16 -0400 Subject: [PATCH 5/9] Bump the version number --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b4fa75f8..0982be4d 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,7 @@ def load_requirements(*requirements_paths): setup( name='xblock-sdk', - version='0.1a0', + version='1.0', description='XBlock SDK', packages=[ 'sample_xblocks', From cd097f47776ff0bbb6fa233cce141b704260dec7 Mon Sep 17 00:00:00 2001 From: muzaffaryousaf Date: Tue, 3 Nov 2015 19:13:10 +0500 Subject: [PATCH 6/9] Updating test requirements. --- requirements/test.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/requirements/test.txt b/requirements/test.txt index 9f9592a5..16ce858e 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,9 +1,10 @@ coverage +ddt mock -pylint==0.28 +pylint==1.4.4 pep8 rednose -bok_choy==0.3.3 +bok_choy==0.4.3 # Acid xblock -e git+https://github.com/edx/acid-block.git@e46f9cda8a03e121a00c7e347084d142d22ebfb7#egg=acid-xblock From eae8ecde4a1d1550560ddd8cebfb2e2f1dee608f Mon Sep 17 00:00:00 2001 From: muhammad-ammar Date: Fri, 6 Nov 2015 12:03:00 +0500 Subject: [PATCH 7/9] bump library version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0982be4d..3932a427 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,7 @@ def load_requirements(*requirements_paths): setup( name='xblock-sdk', - version='1.0', + version='0.1.1', description='XBlock SDK', packages=[ 'sample_xblocks', From 766c0fa095f1b9ca6b440a6a780fa3c44016c3e9 Mon Sep 17 00:00:00 2001 From: muhammad-ammar Date: Fri, 6 Nov 2015 18:06:35 +0500 Subject: [PATCH 8/9] make django version in >=1.8,<1.9 --- requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/base.txt b/requirements/base.txt index 1cc6b3f3..a2bc1b6e 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,5 +1,5 @@ cookiecutter==0.9.0 -Django==1.8.4 +Django>=1.8,<1.9 lxml requests webob From 3718ffdd3000b05dc543e57e463fab81bc761571 Mon Sep 17 00:00:00 2001 From: muhammad-ammar Date: Fri, 6 Nov 2015 18:44:38 +0500 Subject: [PATCH 9/9] quality fixes --- requirements/test.txt | 2 +- workbench/test/test_scenarios.py | 2 +- workbench/urls.py | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/requirements/test.txt b/requirements/test.txt index 16ce858e..63f22381 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,7 +1,7 @@ coverage ddt mock -pylint==1.4.4 +pylint==0.28 pep8 rednose bok_choy==0.4.3 diff --git a/workbench/test/test_scenarios.py b/workbench/test/test_scenarios.py index cd0a0354..38d71d8c 100644 --- a/workbench/test/test_scenarios.py +++ b/workbench/test/test_scenarios.py @@ -56,7 +56,7 @@ def test_scenario(self, scenario_id): url = reverse('workbench_show_scenario', kwargs={'scenario_id': scenario_id}) client = Client() response = client.get(url, follow=True) - assert response.status_code == 200, name + assert response.status_code == 200, scenario_id # Be sure we got the whole scenario. Again, we can't know what to expect # here, but at the very least, if there are verticals, they should not be diff --git a/workbench/urls.py b/workbench/urls.py index 2a28dd45..b8e1c6a4 100644 --- a/workbench/urls.py +++ b/workbench/urls.py @@ -4,7 +4,6 @@ from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.contrib import admin -from workbench.scenarios import init_scenarios admin.autodiscover()