Merge lp:~clint-fewbar/pyjuju/charm-tests-spec into lp:~juju/pyjuju/docs

Proposed by Clint Byrum
Status: Merged
Approved by: Mark Mims
Approved revision: 15
Merge reported by: Mark Mims
Merged at revision: not available
Proposed branch: lp:~clint-fewbar/pyjuju/charm-tests-spec
Merge into: lp:~juju/pyjuju/docs
Diff against target: 293 lines (+289/-0)
1 file modified
source/charm-tests.rst (+289/-0)
To merge this branch: bzr merge lp:~clint-fewbar/pyjuju/charm-tests-spec
Reviewer Review Type Date Requested Status
Mark Mims (community) Approve
Review via email: mp+91503@code.launchpad.net

Description of the change

This is a draft specification for implementing large scale charm tests.

This is a draft specification for implementing large scale charm tests.

https://codereview.appspot.com/5624044/

To post a comment you must log in.
Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :
Download full text (3.6 KiB)

Thanks Clint. Here are some comments:

https://codereview.appspot.com/5624044/diff/1/source/charm-tests.rst
File source/charm-tests.rst (right):

https://codereview.appspot.com/5624044/diff/1/source/charm-tests.rst#newcode51
source/charm-tests.rst:51: utilized to attach tests to charms. Under the
charm root directory,
"To facilitate tests attached to charms .. to attach tests to charms."

The sentence is a bit self-referential. Would be nice to reword

https://codereview.appspot.com/5624044/diff/1/source/charm-tests.rst#newcode60
source/charm-tests.rst:60: * the default environment is bootstrapped
To be more clear, we might say something like:

* A testing environment is already bootstrapped and is made the default
for command line usage.

https://codereview.appspot.com/5624044/diff/1/source/charm-tests.rst#newcode61
source/charm-tests.rst:61: * The CWD is the charm root directory
I think this should be the "tests/" directory itself. Note that the test
doesn't actually have a strong relation to the content of the charm. The
content is deployed into the remote machine, and the test is sitting
locally. Its interaction will be mainly remote.

https://codereview.appspot.com/5624044/diff/1/source/charm-tests.rst#newcode64
source/charm-tests.rst:64: charm url and/or repository arguments of the
test runner's choice. This
We have to qualify a bit better what the "runner's choice" mean, since a
charmer reading that will feel like "Okay, but _what is the version_?".

Maybe something like "the current version at the moment the test is
run"? This gives us some freedom to move back and forth, and gives the
charmer a vague feeling of what to expect.

https://codereview.appspot.com/5624044/diff/1/source/charm-tests.rst#newcode69
source/charm-tests.rst:69: * a special sub-command of juju,
``deploy-previous``, will deploy the
This command doesn't exist. Would you mind to drop the upgrade aspect
from the specification entirely? I'd be happy to debate about a follow
up improvement once we have the basics in place.

https://codereview.appspot.com/5624044/diff/1/source/charm-tests.rst#newcode76
source/charm-tests.rst:76: * ``~/.juju`` will not be accessible to the
tests
Read-only, maybe? It needs to be accessible for reading purposes or the
command doesn't work.

https://codereview.appspot.com/5624044/diff/1/source/charm-tests.rst#newcode82
source/charm-tests.rst:82: If present, tests/requirements.yaml will be
read to determine packages
Looks good, but can we please name that as "tests/tests.yaml", so that
this may be used for other needs too, when/if they show up?

https://codereview.appspot.com/5624044/diff/1/source/charm-tests.rst#newcode90
source/charm-tests.rst:90: If a tool is needed to perform a test and not
available in the Ubuntu
s/and not/and is not/?

https://codereview.appspot.com/5624044/diff/1/source/charm-tests.rst#newcode111
source/charm-tests.rst:111: running charms, and so may affect the
outcome.
Section looks great.

https://codereview.appspot.com/5624044/diff/1/source/charm-tests.rst#newcode141
source/charm-tests.rst:141: trap teardown EXIT
Destroying the temporary state manually should not be necessary. The
harness should be able to put the...

Read more...

6. By Clint Byrum

Rewording paragraph to be more succinct.

7. By Clint Byrum

clarifying default environment

8. By Clint Byrum

moving CWD to tests directory to encourage better encapsulation of test code

9. By Clint Byrum

using strong language in explanation of charm resolver

10. By Clint Byrum

dropping deploy-previous pending some discussion of how best to test upgrade-charm

11. By Clint Byrum

No need to state this, as it complicates things unnecessarily and is implied by not guaranteeing access to it

12. By Clint Byrum

renaming requirements.yaml to tests.yaml to allow broader usage in the future

13. By Clint Byrum

grammar is our friend

14. By Clint Byrum

Re-merging fixes from email discussion. Moves test runner to the end, adds another example, clarifies exit codes and intended test output.

15. By Clint Byrum

Removing suggestions to cleanup services. Also clarifying output suggestions.

Revision history for this message
Mark Mims (mark-mims) :
review: Approve
Revision history for this message
Mark Mims (mark-mims) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'source/charm-tests.rst'
2--- source/charm-tests.rst 1970-01-01 00:00:00 +0000
3+++ source/charm-tests.rst 2012-02-23 22:37:12 +0000
4@@ -0,0 +1,289 @@
5+==============
6+Charm Testing
7+==============
8+
9+Intro
10+=====
11+
12+**DRAFT**
13+
14+Juju has been designed from the start to foster a large collection of
15+"charms". Charms are expected to number in the thousands, and be self
16+contained, with well defined interfaces for defining their relationships
17+to one another.
18+
19+Because this is a large complex system, not unlike a Linux software
20+distribution, there is a need to test the charms and how they interact
21+with one another. This specification defines a plan for implementing
22+a simple framework to help this happen.
23+
24+Static tests have already been implemented in the ``charm proof`` command
25+as part of ``charm-tools``. Any static testing of charms is beyond the
26+scope of this specification.
27+
28+Phase 1 - Generic tests
29+=======================
30+
31+All charms share some of the same characteristics. They all have a
32+yaml file called ``metadata.yaml``, and when deployed, juju will always
33+attempt to progress the state of the service from install to config to
34+started. Because of this, all charms can be tested using the following
35+algorithm::
36+
37+ deploy charm
38+ while state != started
39+ if timeout is reached, FAIL
40+ if state == install_error, config_error, or start_error, FAIL
41+ if state == started, PASS
42+
43+Other generic tests may be identified, so a collection of generic tests should be the focus of an implementation.
44+
45+Note that this requirement is already satisfied by Mark Mims' jenkins tester:
46+http://charmtests.markmims.com/
47+
48+Phase 2 - Charm Specific tests
49+==============================
50+
51+Charm authors will have the best insight into whether or not a charm is
52+working properly.
53+
54+A simple structure will be utilized to attach tests to charms. Under the
55+charm root directory, a sub-directory named 'tests' will be scanned by
56+a test runner for executable files matching the glob ``*.test``. These
57+will be run in lexical order by the test runner, with a predictible
58+environment. The tests can make the following assumptions:
59+
60+* A minimal install of the release of Ubuntu which the charm is targetted
61+ at will be available.
62+* A version of juju is installed and available in the system path.
63+* A juju environment with no services deployed inside it is already
64+ bootstrapped, and will be the default for command line usage.
65+* The CWD is the ``tests`` directory off the charm root.
66+* Full network access to deployed nodes will be allowed.
67+* the bare name of any charm in arguments to juju will be resolved to a
68+ charm url and/or repository arguments of the test runner's choice. This
69+ means that if you need mysql, you do not do ``juju deploy cs:mysql`` or
70+ ``juju deploy --repository ~/charms local:mysql``, but just ``juju deploy
71+ mysql``. A wrapper will resolve this to the latest version of the
72+ given charm from the list of official charms.
73+
74+The following restrictions may be enforced:
75+
76+* Internet access will be restricted from the testing host.
77+
78+If present, tests/tests.yaml will be read to determine packages
79+that need to be installed on the host running tests in order to facilitate
80+the tests. The packages can *only* be installed from the official,
81+default Ubuntu archive for the release which the charm is intended for,
82+from any of the repositories enabled by default in said release. The
83+format of tests.yaml is as such::
84+
85+ packages: [ package1, package2, package3 ]
86+
87+If a tool is needed to perform a test and is not available in the Ubuntu
88+archive, it can also be included in the ``tests/`` directory, as long
89+as the file which contains it does not end in ``.test``. Note that build
90+tools cannot be assumed to be available on the testing system.
91+
92+Purpose of tests
93+----------------
94+
95+The purpose of these tests is to assert that the charm works well on the
96+intended platform and performs the expected configuration steps. Examples
97+of things to test in each charm beyond install/start is:
98+
99+* After install, expose, and adding of required relations, the service is
100+ listening on the intended ports and is functional.
101+* Adding, removing, and re-adding a relation should work without error.
102+* Setting config values should result in the config value reflected in
103+ the service's configuraion.
104+* Adding multiple units to a web app charm and relating to a load balancer
105+ results in the same HTML on both units directly and the load balancer.
106+
107+Exit Codes
108+----------
109+
110+Upon exit, the test's exit code will be evaluated to mean the following:
111+
112+* 0: Test passed
113+* 1: Failed test
114+* 100: Test is skipped because of incomplete environment
115+
116+Output
117+------
118+
119+There is a general convention which output should follow, though it will
120+not be interpreted by machine. On stdout, a message indicating the reason
121+for the exit code should be printed, with a prefix string corresponding to
122+the exit codes defined above. The correlation is:
123+
124+* PASS - 0
125+* FAIL - 1
126+* SKIP - 100
127+
128+Anything else intentional should be prefixed with the word 'INFO'. If the
129+contents of files are to be logged, the contents should be preceeded by
130+``INFO: BEGIN filename``, where filename is a logical name unique to
131+this run of the test, and then the file ended with ``INFO: END filename``.
132+
133+Example Tests
134+-------------
135+
136+Deploy requirements and Poll
137+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
138+
139+The test below [*]_ deploys mediawiki with mysql and memcached related to it,
140+and then tests to make sure it returns a page via http with "<title>"
141+somewhere in the content.::
142+
143+
144+ #!/bin/sh
145+
146+ set -e
147+
148+ teardown() {
149+ if [ -n "$datadir" ] ; then
150+ if [ -f $datadir/passed ]; then
151+ rm -r $datadir
152+ else
153+ echo INFO: $datadir preserved
154+ if [ -f $datadir/wget.log ] ; then
155+ echo INFO: BEGIN wget.log
156+ cat $datadir/wget.log
157+ echo INFO: END wget.log
158+ fi
159+ fi
160+ fi
161+ }
162+ trap teardown EXIT
163+
164+
165+ juju deploy mediawiki
166+ juju deploy mysql
167+ juju deploy memcached
168+ juju add-relation mediawiki:db mysql:db
169+ juju add-relation memcached mediawiki
170+ juju expose mediawiki
171+
172+ for try in `seq 1 600` ; do
173+ host=`juju status | tests/get-unit-info mediawiki public-address`
174+ if [ -z "$host" ] ; then
175+ sleep 1
176+ else
177+ break
178+ fi
179+ done
180+
181+ if [ -z "$host" ] ; then
182+ echo FAIL: status timed out
183+ exit 1
184+ fi
185+
186+ datadir=`mktemp -d ${TMPDIR:-/tmp}/wget.test.XXXXXXX`
187+ echo INFO: datadir=$datadir
188+
189+ wget --tries=100 --timeout=6 http://$host/ -O - -a $datadir/wget.log | grep -q '<title>'
190+
191+ if [ $try -eq 600 ] ; then
192+ echo FAIL: Timed out waiting.
193+ exit 1
194+ fi
195+
196+ touch $datadir/passed
197+
198+ trap - EXIT
199+ teardown
200+
201+ echo PASS
202+ exit 0
203+
204+Test config settings
205+~~~~~~~~~~~~~~~~~~~~
206+
207+The following example tests checks to see if the default_port change
208+the admin asks for is actually respected post-deploy::
209+
210+ #!/bin/sh
211+
212+ if [ -z "`which nc`" ] ; then
213+ echo "SKIP: cannot run tests without netcat"
214+ exit 100
215+ fi
216+
217+ set -e
218+
219+ juju deploy mongodb
220+ juju expose mongodb
221+
222+ for try in `seq 1 600` ; do
223+ host=`juju status | tests/get-unit-info mongodb public-address`
224+ if [ -z "$host" ] ; then
225+ sleep 1
226+ else
227+ break
228+ fi
229+ done
230+
231+ if [ -z "$host" ] ; then
232+ echo FAIL: status timed out
233+ exit 1
234+ fi
235+
236+ assert_is_listening() {
237+ local port=$1
238+ listening=""
239+ for try in `seq 1 10` ; do
240+ if ! nc $host $port < /dev/null ; then
241+ continue
242+ fi
243+ listening="$port"
244+ break
245+ done
246+
247+ if [ -z "$listening" ] ; then
248+ echo "FAIL: not listening on port $port after 10 retries"
249+ return 1
250+ else
251+ echo "PASS: listening on port $listening"
252+ return 0
253+ fi
254+ }
255+
256+ assert_is_listening 27017
257+
258+ juju set mongodb default_port=55555
259+
260+ assert_is_listening 55555
261+ echo PASS: config change tests passed.
262+ exit 0
263+
264+.. [*] get-unit-info
265+ The example tests script uses a tool that is not widely available yet,
266+ ``get-unit-info``. In the future enhancements should be made to juju
267+ core to allow such things to be made into plugins. Until then, it can
268+ be included in each test dir that uses it, or we can build a package
269+ of tools that are common to tests.
270+
271+Test Runner
272+===========
273+
274+A test runner will periodically poll the collection of charms for changes
275+since the last test run. If there have been changes, the entire set of
276+changes will be tested as one delta. This delta will be recorded in the
277+test results in such a way where a developer can repeat the exact set
278+of changes for debugging purposes.
279+
280+All of the charms will be scanned for tests in lexical order by
281+series, charm name, branch name. Non official charms which have not
282+been reviewed by charmers will not have their tests run until the test
283+runner's restrictions have been vetted for security, since we will be
284+running potentially malicious code. It is left to the implementor to
285+determine what mix of juju, client platform, and environment settings
286+are appropriate, as all of these are variables that will affect the
287+running charms, and so may affect the outcome.
288+
289+If tests exit with services still in the environment, the test runner
290+may clean them up, whether by destroying the environment or destroying
291+the services explicitly, and the machines may be terminated as well.
292+Any artifacts needed from the test machines should be retrieved and
293+displayed before the test exits.

Subscribers

People subscribed via source and target branches