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

Subscribers

People subscribed via source and target branches