← Back to team overview

wordpress-charmers team mailing list archive

[Merge] ~barryprice/charm-k8s-wordpress/+git/charm-k8s-wordpress:master into charm-k8s-wordpress:master

 

Barry Price has proposed merging ~barryprice/charm-k8s-wordpress/+git/charm-k8s-wordpress:master into charm-k8s-wordpress:master.

Commit message:
Set up our first basic unit test

Requested reviews:
  Canonical IS Reviewers (canonical-is-reviewers)
  Wordpress Charmers (wordpress-charmers)

For more details, see:
https://code.launchpad.net/~barryprice/charm-k8s-wordpress/+git/charm-k8s-wordpress/+merge/376327
-- 
Your team Wordpress Charmers is requested to review the proposed merge of ~barryprice/charm-k8s-wordpress/+git/charm-k8s-wordpress:master into charm-k8s-wordpress:master.
diff --git a/Makefile b/Makefile
index 6dc2159..3891e12 100644
--- a/Makefile
+++ b/Makefile
@@ -2,5 +2,20 @@ lint:
 	black -l 120 -t py37 reactive/
 	flake8 reactive/
 
+unittest:
+	@tox -e unit
+
+test: lint unittest
+
 build: lint
 	charm build
+
+clean:
+	@echo "Cleaning files"
+	@rm -rf ./.tox
+	@rm -rf ./.pytest_cache
+	@rm -rf ./tests/unit/__pycache__ ./reactive/__pycache__ ./lib/__pycache__
+	@rm -rf ./.coverage ./.unit-state.db
+
+
+.PHONY: lint test unittest build clean
diff --git a/reactive/wordpress.py b/reactive/wordpress.py
index ededd46..39ea6dc 100644
--- a/reactive/wordpress.py
+++ b/reactive/wordpress.py
@@ -14,6 +14,7 @@ from charms.reactive import hook, when, when_not
 
 @hook("upgrade-charm")
 def upgrade_charm():
+    status.maintenance("maintenance", "Upgrading charm")
     reactive.clear_flag("wordpress.configured")
 
 
@@ -136,7 +137,6 @@ def first_install():
         hookenv.log("No initial_setting provided or wordpress already configured. Skipping first install.")
         return True
     hookenv.log("Starting wordpress initial configuration")
-    # TODO: more of the below ought to be configurable
     payload = {"admin_password": host.pwgen(24), "blog_public": "checked", "Submit": "submit"}
     payload.update(safe_load(config["initial_settings"]))
     payload["admin_password2"] = payload["admin_password"]
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..888e37a
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+# Include python requirements here
+requests
diff --git a/tests/unit/requirements.txt b/tests/unit/requirements.txt
new file mode 100644
index 0000000..2d27572
--- /dev/null
+++ b/tests/unit/requirements.txt
@@ -0,0 +1,7 @@
+requests
+charmhelpers
+charms.reactive
+freezegun
+mock
+pytest
+pytest-cov
diff --git a/tests/unit/test_wordpress.py b/tests/unit/test_wordpress.py
new file mode 100644
index 0000000..5ade069
--- /dev/null
+++ b/tests/unit/test_wordpress.py
@@ -0,0 +1,64 @@
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+from unittest import mock
+
+# We also need to mock up charms.layer so we can run unit tests without having
+# to build the charm and pull in layers such as layer-status.
+sys.modules['charms.layer'] = mock.MagicMock()
+
+from charms.layer import status  # NOQA: E402
+
+# Add path to where our reactive layer lives and import.
+sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
+from reactive import wordpress  # NOQA: E402
+
+
+class TestCharm(unittest.TestCase):
+    def setUp(self):
+        self.maxDiff = None
+        self.tmpdir = tempfile.mkdtemp(prefix='charm-unittests-')
+        self.addCleanup(shutil.rmtree, self.tmpdir)
+
+        self.charm_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
+
+        patcher = mock.patch('charmhelpers.core.hookenv.log')
+        self.mock_log = patcher.start()
+        self.addCleanup(patcher.stop)
+        self.mock_log.return_value = ''
+
+        patcher = mock.patch('charmhelpers.core.hookenv.charm_dir')
+        self.mock_charm_dir = patcher.start()
+        self.addCleanup(patcher.stop)
+        self.mock_charm_dir.return_value = self.charm_dir
+
+        patcher = mock.patch('charmhelpers.core.hookenv.local_unit')
+        self.mock_local_unit = patcher.start()
+        self.addCleanup(patcher.stop)
+        self.mock_local_unit.return_value = 'mock-wordpress/0'
+
+        patcher = mock.patch('charmhelpers.core.hookenv.config')
+        self.mock_config = patcher.start()
+        self.addCleanup(patcher.stop)
+        self.mock_config.return_value = {'blog_hostname': 'myblog.example.com'}
+
+        patcher = mock.patch('charmhelpers.core.host.log')
+        self.mock_log = patcher.start()
+        self.addCleanup(patcher.stop)
+        self.mock_log.return_value = ''
+
+        status.active.reset_mock()
+        status.blocked.reset_mock()
+        status.maintenance.reset_mock()
+
+    @mock.patch('charms.reactive.clear_flag')
+    def test_hook_upgrade_charm_flags(self, clear_flag):
+        '''Test correct flags set via upgrade-charm hook'''
+        wordpress.upgrade_charm()
+        self.assertFalse(status.maintenance.assert_called())
+        want = [
+            mock.call('wordpress.configured'),
+        ]
+        self.assertFalse(clear_flag.assert_has_calls(want, any_order=True))
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..7b45934
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,45 @@
+[tox]
+skipsdist=True
+envlist = unit, functional
+skip_missing_interpreters = True
+
+[testenv]
+basepython = python3
+setenv =
+  PYTHONPATH = .
+
+[testenv:unit]
+commands =
+    pytest --ignore {toxinidir}/tests/functional \
+      {posargs:-v  --cov=reactive --cov-report=term-missing --cov-branch}
+deps = -r{toxinidir}/tests/unit/requirements.txt
+       -r{toxinidir}/requirements.txt
+setenv =
+  PYTHONPATH={toxinidir}/lib
+  TZ=UTC
+
+[testenv:functional]
+passenv =
+  HOME
+  JUJU_REPOSITORY
+  PATH
+commands =
+	pytest -v --ignore {toxinidir}/tests/unit {posargs}
+deps = -r{toxinidir}/tests/functional/requirements.txt
+       -r{toxinidir}/requirements.txt
+
+[testenv:black]
+commands = black --skip-string-normalization --line-length=120 .
+deps = black
+
+[testenv:lint]
+commands = flake8
+deps = flake8
+
+[flake8]
+exclude =
+    .git,
+    __pycache__,
+    .tox,
+max-line-length = 120
+max-complexity = 10

References