root/funkload/trunk/README.txt

Revision 52912, 33.9 kB (checked in by bdelbosc, 1 month ago)

handle code 303 as a 302, ready for 1.8.0 release

  • Property svn:keywords set to Id
Line 
1 =========
2 FunkLoad_
3 =========
4
5 :author: Benoit Delbosc
6
7 :address: bdelbosc _at_ nuxeo.com
8
9 :version: FunkLoad/1.8.0
10
11 :revision: $Id$
12
13 :Copyright: (C) Copyright 2005 Nuxeo SAS (http://nuxeo.com).
14     This program is free software; you can redistribute it and/or
15     modify it under the terms of the GNU General Public License
16     version 2 as published by the Free Software Foundation.
17     This program is distributed in the hope that it will be useful, but
18     WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
20     Public License for more details.
21     You should have received a copy of the GNU General Public License along
22     with this program; if not, write to the Free Software Foundation, Inc.,
23     59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25
26 :abstract: This document describes the usage of the FunkLoad_ tool. This tool
27     enables to do functional and load testing of web application.
28
29
30 .. sectnum::    :depth: 2
31
32 .. contents:: Table of Contents
33
34
35 Introducing FunkLoad
36 ====================
37
38 What is FunkLoad ?
39 ------------------
40
41 FunkLoad_ is a functional and load web tester, written in Python, whose
42 main use cases are:
43
44 * Functional testing of web projects, and thus regression testing as well.
45
46 * Performance testing: by loading the web application and monitoring
47   your servers it helps you to pinpoint bottlenecks, giving a detailed
48   report of performance measurement.
49
50 * Load testing tool to expose bugs that do not surface in cursory testing,
51   like volume testing or longevity testing.
52
53 * Stress testing tool to overwhelm the web application resources and test
54   the application recoverability.
55
56 * Writing web agents by scripting any web repetitive task, like checking if
57   a site is alive.
58
59
60 Main FunkLoad_ features are:
61
62 * FunkLoad_ is free software distributed under the `GNU GPL`_.
63
64 * Functional test are pure Python scripts using the pyUnit_ framework like
65   normal unit test. Python enable complex scenarios to handle real world
66   applications.
67
68 * Truly emulates a web browser (single-threaded) using Richard Jones'
69   webunit_:
70
71   - basic authentication support
72   - cookies support
73   - referrer support
74   - fetching css, javascript and images
75   - emulating a browser cache
76   - file upload and multipart/form-data submission
77   - https support
78   - http_proxy support
79
80 * Advanced test runner with many command-line options:
81
82   - set the target server url
83   - display the fetched page in real time in your browser
84   - debug mode
85   - check performance of a single page (or set of pages) inside a test
86   - green/red color mode
87   - select or exclude tests cases using a regex
88   - support normal pyUnit_ test
89   - support doctest_ from a plain text file or embedded in python docstring
90
91 * Turn a functional test into a load test: just by invoking the bench runner
92   you can identify scalability and performance problems.
93
94 * Detailed bench reports in ReST or HTML (and PDF via ps2pdf)
95   containing:
96
97   - the bench configuration
98   - tests, pages, requests stats and charts.
99   - the 5 slowest requests.
100   - servers cpu usage, load average, memory/swap usage and network traffic
101     charts.
102   - an http error summary list
103
104 * Easy test customization using a configuration file or command line options.
105
106 * Easy test creation using TCPWatch_ as proxy recorder, so you can use your web
107   browser and produce a FunkLoad_ test automatically.
108
109 * Provides web assertion helpers.
110
111 * Provides a funkload.CPSTestCase to ease Zope_ and Nuxeo_ CPS_ testing.
112
113 * Easy to install (EasyInstall_) and use, see examples in the demo_ folder.
114
115 * Works fine with CPS or any Zope application, CherryPy, Nuxeo EP or any
116   JBoss Seam application ...
117
118
119 Where to find FunkLoad ?
120 ------------------------
121
122 Either:
123
124 * Latest stable package using EasyInstall_::
125
126    sudo easy_install -U funkload
127
128 * EasyInstall_ the latest snapshot ::
129
130    sudo easy_install -f http://funkload.nuxeo.org/snapshots/ funkload
131
132 * Bleeding edge `svn sources`_::
133
134    easy_install -eb . funkload==dev
135    # or
136    svn co http://svn.nuxeo.org/pub/funkload/trunk funkload
137
138
139 See CHANGES_ file for information about distribution contents.
140
141
142 Installation
143 ------------
144
145 See the INSTALL_ file for requirement and installation.
146
147
148 Examples
149 --------
150
151 See the demo_ folder contents and a report_ example.
152
153 For package installed with easy_install you need to run ``fl-install-demo``
154 to extract the demo examples.
155
156
157 Documentation
158 -------------
159
160 This page is the main FunkLoad_ documentation, there are also:
161
162 * CHANGES_ for information about distribution contents.
163 * INSTALL_ for requirement and installation.
164 * API_ documentation generated with epydoc_.
165 * SLIDES_ introducing FunkLoad_.
166
167
168 Credits
169 -------
170
171 Thanks to Frank Cohen's TestMaker_ framework and Richard Jones webunit_
172 package.
173
174
175 Test runner
176 ===========
177
178 A FunkLoad_ test can be used like a standard unittest using a unittest.main()
179 and a 'python MyFile.py'.
180
181 To ease testing FunkLoad_ come with an advanced test runner to override
182 the static configuration file.
183
184 The ``loop-on-pages`` option enable to check response time of some specific
185 pages inside a test without changing the script, which make easy to tune a
186 page in a complex context. Use the ``debug`` option to find the page numbers.
187
188 Note that ``fl-run-test`` can be used to launch normal unittest.TestCase and
189 (if you use python2.4) doctest_ in a plain text file or embedded in a python
190 docstring. The ``--debug`` option makes doctests verbose.
191
192
193 Usage
194 -----
195 ::
196
197   fl-run-test [options] file [class.method|class|suite] [...]
198
199
200 Examples
201 --------
202 ::
203
204   fl-run-test myFile.py
205                         Run all tests (including doctest with python2.4).
206   fl-run-test myFile.py test_suite
207                         Run suite named test_suite.
208   fl-run-test myFile.py MyTestCase.testSomething
209                         Run a single test MyTestCase.testSomething.
210   fl-run-test myFile.py MyTestCase
211                         Run all 'test*' test methods in MyTestCase.
212   fl-run-test myFile.py MyTestCase -u http://localhost
213                         Same against localhost.
214   fl-run-test myDocTest.txt
215                         Run doctest from plain text file (requires python2.4).
216   fl-run-test myDocTest.txt -d
217                         Run doctest with debug output (requires python2.4).
218   fl-run-test myfile.py -V
219                         Run default set of tests and view in real time each
220                         page fetch with firefox.
221   fl-run-test  myfile.py MyTestCase.testSomething -l 3 -n 100
222                         Run MyTestCase.testSomething, reload one hundred
223                         time the page 3 without concurrency and as fast as
224                         possible. Output response time stats. You can loop
225                         on many pages using slice -l 2:4.
226   fl-run-test myFile.py -e [Ss]ome
227                         Run all tests that match the regex [Ss]ome.
228   fl-run-test myFile.py -e '!foo$'
229                         Run all tests that does not ends with foo.
230   fl-run-test myFile.py --list
231                         List all the test names.
232   fl-run-test -h
233                         More options.
234
235
236 Options
237 -------
238 ::
239
240   --version               show program's version number and exit
241   --help, -h              show this help message and exit
242   --quiet, -q             Minimal output.
243   --verbose, -v           Verbose output.
244   --debug, -d             FunkLoad and doctest debug output.
245   --debug-level=DEBUG_LEVEL
246                           Debug level 2 is more verbose.
247   --url=MAIN_URL, -uMAIN_URL
248                           Base URL to bench without ending '/'.
249   --sleep-time-min=FTEST_SLEEP_TIME_MIN, -mFTEST_SLEEP_TIME_MIN
250                           Minumum sleep time between request.
251   --sleep-time-max=FTEST_SLEEP_TIME_MAX, -MFTEST_SLEEP_TIME_MAX
252                           Maximum sleep time between request.
253   --dump-directory=DUMP_DIR
254                           Directory to dump html pages.
255   --firefox-view, -V      Real time view using firefox, you must have a running
256                           instance of firefox in the same host.
257   --no-color              Monochrome output.
258   --loop-on-pages=LOOP_STEPS, -lLOOP_STEPS
259                           Loop as fast as possible without concurrency on pages
260                           expect a page number or a slice like 3:5. Output some
261                           statistics.
262   --loop-number=LOOP_NUMBER, -nLOOP_NUMBER
263                           Number of loop.
264   --accept-invalid-links  Do not fail if css/image links are not reachable.
265   --simple-fetch          Don't load additional links like css or images when
266                           fetching an html page.
267   --stop-on-fail          Stop tests on first failure or error.
268   --regex=REGEX, -eREGEX  The test names must match the regex.
269   --list                  Just list the test names.
270
271
272
273
274 Benching
275 ========
276
277 The same FunkLaod test can be turned into a load test, just by invoking the
278 bench runner ``fl-run-bench``.
279
280 Principle
281 ---------
282
283 Here are some definitions used in bench mode:
284
285 * CUs: Concurrent Users, which is the number of threads.
286 * STPS: Average of Successful Tests Per Second during a cycle.
287 * SPPS: Average of Successfully Page Per Second during a cycle.
288 * RPS: Average Request Per Second, successfully or not.
289 * max[STPS|SPPS|RPS]: maximum of STPS|SPPS|RPS for a cycle.
290
291 Page
292 ~~~~
293
294 A page is an http get/post request with associated sub requests like
295 redirects, images or links (css, js files). This is what users see as a
296 single page.
297
298
299 Test
300 ~~~~
301
302 A test is made with 3 methods: setUp/test_name/tearDown. During the test_name
303 method each get/post request is called a page.
304
305 ::
306
307   [setUp][page 1]    [page 2] ... [page n]   [tearDown]
308   ======================================================> time
309          <----------------------------------> test method
310                  <--> sleeptime_min to sleeptime_max
311          <-----> page 1 connection time
312
313 Cycle
314 ~~~~~
315
316 A cycle is a load of n concurrents test during a 'duration' period.
317 Threads are launched every 'startupdelay' seconds, each thread executes
318 test in a loop.
319
320 Once all threads have been started we start to record stats.
321
322 Only tests that end during the 'duration' period are taken into account
323 for the test stats (in the representation below test like [---X are not
324 take into account).
325
326 Only pages and requests that finish during the 'duration' are taken into
327 account for the request and pages statistic
328
329 Before a cycle a setUpCycle method is called, after a cycle a tearDownCycle
330 method is called, you can use these methods to test differents server
331 configuration for each cycle.
332
333 ::
334
335   Threads
336   ^
337   |
338   |
339   |n                   [---test--]   [--------]   [--|---X
340   |...
341   |                    |                             |
342   |2            [------|--]   [--------]   [-------] |
343   |                    |                             |
344   |1          [------X | [--------]   [-------]   [--|--X
345   |                    |                             |
346   |[setUpCycle]        |                             |    [tearDownCycle]
347   ===========================================================> time
348                        <------ cycle duration ------->
349    <----- staging ----->                             <---- staging ----->
350               <-> startupdelay    <---> sleeptime
351
352
353 Cycles
354 ~~~~~~
355
356 FunkLoad_ can execute many cycles with different number of CUs, this way you
357 can find easily the maximum number of users that your application can
358 handle.
359
360 Running n cycles with the same CUs is a good way to see how the application
361 handles a writing test over time.
362
363 Running n cycles with the same CUs with a reading test and a setUpCycle that
364 change the application configuration will help you to find the right tuning.
365
366
367 ::
368
369   cvus = [n1, n2, ...]
370
371   Threads
372   ^
373   |
374   |
375   |n2                            __________
376   |                             /          \
377   |                            /            \
378   |n1   _________             /              \
379   |    /         \           /                \
380   |   /           \         /                  \
381   |  /             \       /                    \
382    ==================================================> time
383         <------->   duration     <-------->
384                     <-----> cycle sleep time
385
386
387
388 Bench runner
389 ------------
390
391 Usage
392 ~~~~~
393 ::
394
395   fl-run-bench [options] file class.method
396
397
398 Examples
399 ~~~~~~~~
400 ::
401
402   fl-run-bench myFile.py MyTestCase.testSomething
403                         Bench MyTestCase.testSomething using MyTestCase.conf.
404   fl-run-bench -u http://localhost:8080 -c 10:20 -d 30 myFile.py MyTestCase.testSomething
405                         Bench MyTestCase.testSomething on localhost:8080
406                         with 2 cycles of 10 and 20 users during 30s.
407   fl-run-bench -h
408                         More options.
409
410 Options
411 ~~~~~~~
412 ::
413
414   --version               show program's version number and exit
415   --help, -h              show this help message and exit
416   --url=MAIN_URL, -uMAIN_URL
417                           Base URL to bench.
418   --cycles=BENCH_CYCLES, -cBENCH_CYCLES
419                           Cycles to bench, this is a list of number of virtual
420                           concurrent users, to run a bench with 3 cycles with 5,
421                           10 and 20 users use: -c 2:10:20
422   --duration=BENCH_DURATION, -DBENCH_DURATION
423                           Duration of a cycle in seconds.
424   --sleep-time-min=BENCH_SLEEP_TIME_MIN, -mBENCH_SLEEP_TIME_MIN
425                           Minimum sleep time between request.
426   --sleep-time-max=BENCH_SLEEP_TIME_MAX, -MBENCH_SLEEP_TIME_MAX
427                           Maximum sleep time between request.
428   --startup-delay=BENCH_STARTUP_DELAY, -sBENCH_STARTUP_DELAY
429                           Startup delay between thread.
430   --no-color              Monochrome output.
431   --accept-invalid-links  Do not fail if css/image links are not reachable.
432   --simple-fetch          Don't load additional links like css or images when
433                           fetching an html page.
434
435
436 Tips
437 ----
438
439 Here are few remarks/advices to obtain workable metrics.
440
441 * Since it uses significant CPU resources, make sure that performance limits
442   are not hit by FunkLoad_ before your server's limit is reached.
443   Check this by launching a bench from another host.
444
445 * Having a cycle with one user gives a usefull reference.
446
447 * A bench is composed of a benching test (or scenario) run many times. A good
448   benching test should not be too long so you have a higher testing rate (that
449   is, more benching tests can come to their end).
450
451 * The cycle duration for the benching test should be long enough.
452   Around 5 times the duration of a single benching test is a value that is
453   usually a safe bet. You can obtain this duration of a single benching test by
454   running ``fl-run-test myfile.py MyTestCase.testSomething``.
455
456   Rationale : Normally a cycle duration of a single benching test should be
457   enough. But from the testing platform side if there are more than one
458   concurrent user, there are many threads to start and it takes some time. And on
459   from the tested platform side it is common that a benching test will last
460   longer and longer as the server is used by more and more users.
461
462 * You should use many cycles with the same step interval to produce readable
463   charts (1:10:20:30:40:50:60 vs 1:10:100)
464
465 * A benching test must have the same number of page and in the same
466   order.
467
468 * Use a Makefile to make reproductible bench.
469
470 * There is no debug option while doing a bench (since this would be illegible
471   with all the threads). So, if a bench fails (that is using `fl-run-bench`),
472   use ``fl-run-test -d`` to debug.
473
474 * Using `fl-record` is very easy and very fast to create a scenario. But since
475   it doesn't support HTTPS, the good practise is to first record a scenario
476   with `fl-record` on HTTP, and then change the `url` back to `https` in your
477   FunkLoad test configuration file.
478
479 * Always use description in post/get/xmlrpc, this improves the
480   readability of the report.
481
482
483 Bench report
484 ============
485
486 To produce an HTML or ReST report you need to invoke the ``fl-build-report``,
487 you can easily produce PDF report using Firefox 'Print To File' in
488 PostScript then use the ps2pdf converter.
489
490 Usage
491 -----
492 ::
493
494   fl-build-report [options] xmlfile
495
496 ``fl-build-report`` analyze a FunkLoad_ bench xml result file and output a
497 report.
498
499
500 Examples
501 --------
502 ::
503
504   fl-build-report funkload.xml
505                         ReST rendering into stdout.
506   fl-build-report --html -o /tmp funkload.xml
507                         Build an HTML report in /tmp.
508   fl-build-report -h
509                         More options.
510
511 Options
512 -------
513 ::
514
515     --version               show program's version number and exit
516     --help, -h              show this help message and exit
517     --html, -H              Produce an html report.
518     --output-directory=OUTPUT_DIR, -oOUTPUT_DIR
519                             Directory to store reports.
520
521
522  Note that you can preview the report for cycles that have been done while
523  the bench is still running by invoking the above command.
524
525
526
527 Test Recorder
528 =============
529
530
531 Recording a new FunkLoad test
532 -----------------------------
533
534 Starting with FunkLoad_ 1.3.0 you can use ``fl-record`` to record your
535 navigator activity, this requires the TCPWatch_ python proxy see INSTALL_
536 for information on how to install TCPWatch_.
537
538 1. Start the recorder::
539
540     fl-record basic_navigation
541
542
543   This will output something like this::
544
545     Hit Ctrl-C to stop recording.
546     HTTP proxy listening on :8090
547     Recording to directory /tmp/tmpaYDky9_funkload.
548
549
550 2. Setup your browser proxy and play your scenario
551
552   * in Firefox: Edit > Preferencies > General; Connection Settings set
553     `localhost:8090` as your HTTP proxy
554
555   * Play your scenario using your navigator
556
557   * Hit Ctrl-C to stop recording::
558
559       ^C
560       # Saving uploaded file: foo.png
561       # Saving uploaded file: bar.pdf
562       Creating script: ./test_BasicNavigation.py.
563       Creating configuration file: ./BasicNavigation.conf.
564
565
566 3. Replay you scenario::
567
568      fl-run-test -dV test_BasicNavigation.py
569
570   You should see all the steps on your navigator.
571
572 4. Implement the dynamic part and assertion
573
574   * Code the dynamic part like getting new url of a created document
575   * Add assertion using FunkLoad_ helpers
576   * Use a credential server if you want to make a bench with different users
577     or simply don't want to hard code your login/password.
578
579
580 Note that ``fl-record`` works fine with multi-part encoded form and file upload
581 but will failed to record https session.
582
583 Note that ``fl-record`` will handle automaticly JSF Myfaces token, which
584 enable to easily record and play any JBoss Seam application.
585
586
587 The fl-record command
588 ---------------------
589
590 Usage
591 ~~~~~
592 ::
593
594     fl-record [options] [test_name]
595
596   fl-record launch a TCPWatch_ proxy and record activities, then output
597   a FunkLoad script or generates a FunkLoad unit test if test_name is specified.
598   The default proxy port is 8090.
599
600   Note that tcpwatch.py executable must be accessible from your env.
601
602
603 Examples
604 ~~~~~~~~
605 ::
606
607   fl-record foo_bar
608                         Run a proxy and create a FunkLoad test case,
609                         generates test_FooBar.py and FooBar.conf file.
610                         To test it:  fl-run-test -dV test_FooBar.py
611   fl-record -p 9090
612                         Run a proxy on port 9090, output script to stdout.
613   fl-record -i /tmp/tcpwatch
614                         Convert a tcpwatch capture into a script.
615
616 Options
617 ~~~~~~~
618 ::
619
620   --version               show program's version number and exit
621   --help, -h              show this help message and exit
622   --verbose, -v           Verbose output
623   --port=PORT, -pPORT     The proxy port.
624   --tcp-watch-input=TCPWATCH_PATH, -iTCPWATCH_PATH
625                           Path to an existing tcpwatch capture.
626
627
628 Credential server
629 =================
630
631 If you are writing a bench that requires to be logged with different users
632 FunkLoad_ provides an xmlrpc credential server to serve login/pwd between the
633 different threads.
634
635 It requires 2 files (like unix /etc/passwd and /etc/group) the password file
636 have the following format::
637
638   login1:pwd1
639   ...
640
641 The group file format is::
642
643   group1:user1, user2
644   group2:user2
645   # you can split group declaration
646   group1:user3
647   ...
648
649 Setup a configuration file like in the demo_/cmf folder, then start the
650 credential server::
651
652   fl-credential-ctl credential.conf start
653
654 More options::
655
656   fl-credential-ctl --help
657
658 See the funkload-demo/cmf example for a credential configuration file.
659
660
661 Monitor server
662 ==============
663
664 If you want to monitor a linux server health during the bench, you have to
665 run a monitor xmlrpc server on the target server, this require to install
666 the FunkLoad_ package.
667
668 On the server side you need to install the FunkLoad_ tool then launch the
669 server using a configuration file (example in the demo_/simple folder.)::
670
671   fl-monitor-ctl monitor.conf start
672
673   # more info
674   fl-monitor-ctl --help
675
676
677 On the bench host side setup your test configuration like this::
678
679   [monitor]
680   hosts = server.to.test.com
681
682   [server.to.test.com]
683   description = The web server
684   port = 8008
685
686 Then run the bench, the report will include server stats.
687
688 Note that you can monitor multiple hosts and that the monitor is linux
689 specific.
690
691
692 The FunkLoadTestCase
693 ====================
694
695 FunkLoadTestCase extends the pyUnit_ unittest.TestCase with browser
696 capabilities, configuration file helpers and assertions helpers. FunkLoad_
697 provides also some tools to generate random inputs and communicate with
698 credential servers.
699
700 Here is an overview of the api, you can find more on
701
702 Browser API
703 -----------
704
705 get
706 ~~~
707 ::
708
709   get(url, params=None, description=None, ok_codes=None)
710
711 This emulates a browser http GET link. It will fetch the url, submits
712 appropriate cookies, follow redirection, register new cookies, load css and
713 javascript.
714
715 It also simulates a browser cache by not reloading a css, a javascript or an
716 image twice.
717
718 Note that this is an emulation with some limitation:
719
720 * It is single threaded (it loads images one after the other)
721 * It does not interpret javascript
722 * See trac_ tickets that starts with `Browser:` for other limitations
723
724 This method returns a webunit_ HTTPResponse.
725
726
727 Parameters:
728
729 - *url* a valid url
730 - *params* a dico of parameters that going to be append to the url like
731   `url?key1=value1&...`
732 - *description* is used on the bench report to describe the user action
733 - *ok_codes* is a list of http expected code like [200:301] if the http
734   response is not in the list `get` will raise a test failure exception,
735   if not provided assume that the default list is [200, 301, 302].
736
737 Note that if the *url* already contains encoded parameters you should not
738 use the *params* parameter.
739
740
741 post
742 ~~~~
743 ::
744
745   post(url, params=None, description=None, ok_codes=None)
746
747
748 Same interface than the get() but it uses a http post method.
749 You can upload a file by setting a params like this::
750
751   from webunit.utility import Upload
752   params['file_up'] = Upload('/tmp/foo.txt')
753
754
755 exists
756 ~~~~~~
757 ::
758
759   exists(url, params=None, description="Checking existence")
760
761
762 Return True if the http response code is 200, 301 or 302, and return False if
763 http code is 404 or 503, other codes will raise a test failure exception.
764
765
766 setBasicAuth
767 ~~~~~~~~~~~~
768 ::
769
770   setBasicAuth(login, password)
771
772 Next requests will use the http basic authentication.
773
774
775 clearBasicAuth
776 ~~~~~~~~~~~~~~
777 ::
778
779   clearBasicAuth()
780
781 Remove basic auth credential set by setBasicAuth.
782
783
784 setUserAgent
785 ~~~~~~~~~~~~
786 ::
787
788   setUserAgent(agent)
789
790 New in 1.3.0. version.
791
792 Set a ``User-Agent`` http header for the next requests, the default browser
793 behaviour is to use the agent defined in the configuration file under
794 ``[main] user_agent`` or to use the default ``FunkLoad/version``
795 string. Using this method enable to change the user agent during a test
796 case.
797
798
799 addHeader
800 ~~~~~~~~~
801 ::
802
803   addHeader(key, value)
804
805 New in 1.3.0. version.
806
807 Add an http header for the next requests.
808
809
810 clearHeaders
811 ~~~~~~~~~~~~
812 ::
813
814   clearHeaders()
815
816 New in 1.3.0. version.
817
818 Remove all headers previously added by `addHeader`_ or `setUserAgent`_,
819 and remove the referer as well.
820
821
822 XML RPC API
823 -----------
824
825 You can test or bench xmlrpc services using the following API.
826
827 xmlrpc
828 ~~~~~~
829 ::
830
831   xmlrpc(url, method_name, params=None, description=None)
832
833 Call the ``method_name`` at ``url`` using xmlrpclib. You can use the
834 setBasicAuth_ method before to handle the http basic authentication. Note
835 that due to xmlrpclib limitation you can not use an http proxy.
836
837 Parameters:
838
839 - *url* the url of the xmlrpc server
840 - *method_name* the name of the procedure to call
841 - *params* a list of parameters to pass to the method
842 - *description* is used on the bench report to describe the action
843
844
845 Assertion helpers API
846 ---------------------
847
848 FunkLoad_ uses the unittest assertion (``assert_``, ``assertEquals``,
849 ``fail``, ...), but provides some methods to check the http response.
850 After fetching a page you can use the following methods.
851
852
853 getLastUrl
854 ~~~~~~~~~~
855 ::
856
857   getLastUrl()
858
859 Return the last accessed page url taking care of redirects.
860
861
862 getLastBaseUrl
863 ~~~~~~~~~~~~~~
864 ::
865
866   getLastBaseUrl()
867
868 Return the <base /> href value of the last accessed page.
869
870
871 listHref
872 ~~~~~~~~
873 ::
874
875   listHref(url_pattern=None, content_pattern=None):
876
877 Return a list of href anchor url present in the last html response,
878 filtering href using the ``url_pattern`` regex if present and filtering the
879 text content of the link with content_pattern if present.
880
881
882 getBody
883 ~~~~~~~
884 ::
885
886   getBody()
887
888 Return the last response content.
889
890
891 The response object
892 ~~~~~~~~~~~~~~~~~~~
893
894 The response returned by a get or post are webunit_ HTTPResponse object
895
896 ::
897
898   response = self.get(url)
899   print "http response code %s" % response.code
900   print "http header location %s" % response.headers['location']
901   self.assert_('HTML' in response.body)
902
903 ::
904
905   response.getDOM().getByName('h1')
906
907 getDOM return a SimpleDOM interface of the fetched html page, see the
908 webunit_ SimpleDOM api instructions for details.
909
910
911
912 Configuration file API
913 ----------------------
914
915 A FunkLoadTestCase class uses a configuration file to setup variable
916 configuration, like the base server url to be tested, the test description,
917 credential access, logging files and other test specific parameters. The test
918 configuration file have the same name of the FunkLoadTestCase with a '.conf'
919 extension. See documented examples in the demo_ folder (``fl-install-demo``).
920
921 conf_get
922 ~~~~~~~~
923 ::
924
925   conf_get(section, key, default=_marker)
926
927 Return an entry from the configuration file. Note that the entry may be
928 overriden by a command line option.
929
930 Parameters:
931
932 - *section* the section in the configuration file.
933 - *key* the key.
934 - *default* a default value.
935
936
937 conf_getInt
938 ~~~~~~~~~~~
939
940 Return an integer.
941
942 conf_getFloat
943 ~~~~~~~~~~~~~
944
945 Return a float.
946
947 conf_getList
948 ~~~~~~~~~~~~
949
950 Additional parameter:
951
952 - *separator* the default separator is a colon ':'.
953
954 Return a list
955
956
957 Logging
958 -------
959
960 A FunkLoadTestCase store its results in an xml file (like request and test
961 result) and put other log information into a text log and/or output to the
962 console.
963
964 logd
965 ~~~~
966 ::
967
968   logd(message)
969
970 Debug log message
971
972 logi
973 ~~~~
974 ::
975
976   logi(message)
977
978 Information log message
979
980
981 Lipsum API
982 ----------
983
984 To generate dummy document contents you can use the funkload.Lipsum api,
985 this is a very simple "Lorem ipsum" generator.
986
987 You can see some examples by doing::
988
989   python -c "from funkload.Lipsum import main; main()"
990
991
992 Lipsum
993 ~~~~~~
994 ::
995
996   from funkload.Lipsum import Lipsum
997   lipsum = Lipsum(vocab=V_ASCII, chars=CHARS, sep=SEP)
998
999 Parameters:
1000
1001 - *vocab* a list of word, Lipsum provide 3 lists V_ASCII, V_DIAC, V_8859_15
1002 - *chars* the list of char used to build an identifier
1003 - *sep* some separators used in sentences like coma, question mark ...
1004
1005
1006 getWord
1007 ~~~~~~~
1008 ::
1009
1010   lipsum.getWord()
1011
1012 Return a random word from the vocabulary.
1013
1014
1015 getUniqWord
1016 ~~~~~~~~~~~
1017 ::
1018
1019   lipsum.getUniqWord(length_min=None, length_max=None):
1020
1021 Generate a kind of uniq id.
1022
1023
1024 getSubject
1025 ~~~~~~~~~~
1026 ::
1027
1028   lipsum.getSubject(length=5, prefix=None, uniq=False,
1029                     length_min=None, length_max=None)
1030
1031 Return a subject of length word.
1032
1033 Parameters:
1034
1035 - *length* the number of words in the subject
1036 - *prefix* a prefix to add at the beginning of a the subject
1037 - *uniq* add an uniq identifier in the subject
1038 - *length_min/max* the words length is a random between min and max
1039
1040
1041 getSentence
1042 ~~~~~~~~~~~
1043 ::
1044
1045   lipsum.getSentence()
1046
1047 Return a sentence with some separators and and a ending point.
1048
1049
1050 getParagraph
1051 ~~~~~~~~~~~~
1052 ::
1053
1054   lipsum.getParagraph(length=4)
1055
1056 Return a paragraph of length sentences.
1057
1058
1059 getMessage
1060 ~~~~~~~~~~
1061 ::
1062
1063   lipsum.getMessage(length=7)
1064
1065 Return a message with length Paragraphs.
1066
1067
1068 getPhoneNumber
1069 ~~~~~~~~~~~~~~
1070 ::
1071
1072   lipsum.getPhoneNumber(lang="fr", format="medium")
1073
1074 Return a random phone number.
1075
1076 Parameters:
1077
1078 - *lang* can be fr or en_US
1079 - *format* can be short, medium or long
1080
1081
1082 getAddress
1083 ~~~~~~~~~~
1084 ::
1085
1086   lipsum.getAddress(lang="fr")
1087
1088 Return a random address.
1089
1090
1091 Utils
1092 -----
1093
1094 To communicate with FunkLoad_ services like the credential server, there are
1095 some wrappers in the utils module.
1096
1097 xmlrpc_get_credential
1098 ~~~~~~~~~~~~~~~~~~~~~
1099 ::
1100
1101   from funkload.utils import xmlrpc_get_credential
1102   xmlrpc_get_credential(credential_host, credential_port, group=None)
1103
1104 Return a tuple login, password of a user that belong to group if specified.
1105
1106 xmlrpc_list_groups
1107 ~~~~~~~~~~~~~~~~~~
1108
1109 List groups name served by the credential server.
1110
1111 xmlrpc_list_credentials
1112 ~~~~~~~~~~~~~~~~~~~~~~~
1113
1114 List all login/password served by the credential server.
1115
1116 FunkLoadDocTest
1117 ===============
1118
1119 Since FunkLoad_ 1.5 you can use funkload easily from a doctest_::
1120
1121     >>> from funkload.FunkLoadDocTest import FunkLoadDocTest
1122     >>> fl = FunkLoadDocTest()
1123     >>> response = fl.get('http://localhost/')
1124     >>> 'HTML' in response.body
1125     True
1126     >>> response
1127     <response url="http://127.0.0.1:80/" code="200" message="OK" />
1128
1129 FunkLoadDocTest_ exposes the same API than `The FunkLoadTestCase`_.
1130
1131 Other Test Cases
1132 ================
1133
1134 The ZopeTestCase
1135 ----------------
1136
1137 This class extends the FunkLoadTestCase providing common Zope_ tasks.
1138
1139 zopeRestart
1140 ~~~~~~~~~~~
1141 ::
1142
1143   zopeRestart(zope_url, admin_id, admin_pwd, time_out=600)
1144
1145 Stop and Start the Zope_ server.
1146
1147 Parameters:
1148
1149 - *zope_url* the zope url.
1150 - *admin_id* and *admin_pwd* the zope admin credential.
1151 - *time_out* maximum time to wait until the zope server restart.
1152
1153 zopePackZodb
1154 ~~~~~~~~~~~~
1155 ::
1156
1157   zopePackZodb(zope_url, admin_id, admin_pwd, database="main", days=0)
1158
1159 Pack a zodb database.
1160
1161 Parameters:
1162
1163 - *database* the database to pack.
1164 - *days* removing previous revision that are older than *days* ago
1165
1166
1167 zopeFlushCache
1168 ~~~~~~~~~~~~~~
1169 ::
1170
1171   zopeFlushCache(zope_url, admin_id, admin_pwd, database="main")
1172
1173 Remove all objects from all ZODB in-memory caches.
1174
1175 zopeAddExternalMethod
1176 ~~~~~~~~~~~~~~~~~~~~~
1177 ::
1178
1179   zopeAddExternalMethod(parent_url, admin_id, admin_pwd,
1180                         method_id, module, function, run_it=True)
1181
1182 Add an External method an run it.
1183
1184 CPSTestCase
1185 -----------
1186
1187 This class extends the ZopeTestCase providing common Nuxeo_ CPS_ tasks. You
1188 need to import the CPSTestCase that works with your CPS_ for example
1189 CPS338TestCAse or CPS340TestCase.
1190
1191
1192 cpsCreateSite
1193 ~~~~~~~~~~~~~
1194 ::
1195
1196   cpsCreateSite(admin_id, admin_pwd,
1197                 manager_id, manager_password,
1198                 manager_mail, langs=None,
1199                 title=None, description=None,
1200                 interface="portlets", zope_url=None, site_id=None)
1201
1202 Build a new CPS_ site.
1203
1204 Parameters:
1205
1206 - *admin_id* and *admin_pwd* the zope admin credential.
1207 - *manager_id* and *manager_pwd* the cps manager credential.
1208 - *zope_url* the Zope_ server url [*]_.
1209 - *site_id* the CPS_ site id.
1210
1211 .. [*] if the zope_url and site_id is not given we guess it using the
1212        server_url
1213
1214
1215 cpsLogin
1216 ~~~~~~~~
1217 ::
1218
1219   cpsLogin(login, password)
1220
1221 CPS log in.
1222
1223 cpsLogout
1224 ~~~~~~~~~
1225
1226 Logout the user logged in using cpsLogin.
1227
1228 cpsCreateGroup
1229 ~~~~~~~~~~~~~~
1230 ::
1231
1232   cpsCreateGroup(group_name)
1233
1234 Create a CPS_ group.
1235
1236 cpsVerifyGroup
1237 ~~~~~~~~~~~~~~
1238 ::
1239
1240   cpsVerifyGroup(group_name)
1241
1242 Create a CPS_ group if not present.
1243
1244 cpsCreateUser
1245 ~~~~~~~~~~~~~
1246 ::
1247
1248   cpsCreateUser(user_id=None, user_pwd=None,
1249                 user_givenName=None, user_sn=None,
1250                 user_email=None, groups=None):
1251
1252
1253 Create a CPS_ users.
1254
1255 cpsVerifyUser
1256 ~~~~~~~~~~~~~
1257
1258 Create a CPS_ users if not present.
1259
1260
1261 cpsSetLocalRole
1262 ~~~~~~~~~~~~~~~
1263 ::
1264
1265   cpsSetLocalRole(url, name, role)
1266
1267 Grant role to name in url.
1268
1269 cpsCreateSection
1270 ~~~~~~~~~~~~~~~~
1271 ::
1272
1273   cpsCreateSection(parent_url, title, description)
1274
1275
1276 cpsCreateWorkspace
1277 ~~~~~~~~~~~~~~~~~~
1278 ::
1279
1280   cpsCreateWorkspace(parent_url, title, description)
1281
1282
1283 cpsCreateDocument
1284 ~~~~~~~~~~~~~~~~~
1285 ::
1286
1287   cpsCreateDocument(parent_url)
1288
1289 Create a random document in the parent_url container.
1290
1291 cpsCreateNewsItem
1292 ~~~~~~~~~~~~~~~~~
1293 ::
1294
1295   cpsCreateNewsItem(parent_url)
1296
1297 Create a simple news in the parent_url container.
1298
1299 cpsChangeUiLanguage
1300 ~~~~~~~~~~~~~~~~~~~
1301 ::
1302
1303   cpsChangeUiLanguage(lang)
1304
1305 Change the ui locale selection
1306
1307
1308 cpsListDocumentHref
1309 ~~~~~~~~~~~~~~~~~~~
1310 ::
1311
1312   cpsListDocumentHref(pattern)
1313
1314 Return a clean list of document href that matches pattern in the previous
1315 page fetched.
1316
1317 cpsSearchDocId
1318 ~~~~~~~~~~~~~~
1319 ::
1320
1321   cpsSearchDocId(doc_id)
1322
1323 Return the list of url that ends with doc_id, using catalog search.
1324
1325
1326 Todo and bugs
1327 =============
1328
1329 * See the trac tickets: http://svn.nuxeo.org/trac/pub/report/12
1330
1331 If you want to report a bug or if you think that something is
1332 missing, send me an email.
1333
1334
1335
1336 .. _FunkLoad: http://funkload.nuxeo.org/
1337 .. _TestMaker: http://www.pushtotest.com/
1338 .. _TCPWatch: http://hathawaymix.org/Software/TCPWatch/
1339 .. _webunit: http://mechanicalcat.net/tech/webunit/
1340 .. _pyUnit: http://pyunit.sourceforge.net/
1341 .. _INSTALL: INSTALL.html
1342 .. _CHANGES: CHANGES.html
1343 .. _API: api/index.html
1344 .. _Slides: http://blogs.nuxeo.com/sections/blogs/fermigier/2005_11_17_slides-introducing
1345 .. _epydoc: http://epydoc.sourceforge.net/
1346 .. _Zope: http://www.zope.org/
1347 .. _Cmf: http://www.zope.org/Products/CMF/
1348 .. _Nuxeo: http://www.nuxeo.com/
1349 .. _CPS: http://www.cps-project.org/
1350 .. _`python cheese shop`: http://www.python.org/pypi/funkload/
1351 .. _EasyInstall: http://peak.telecommunity.com/DevCenter/EasyInstall
1352 .. _demo: http://svn.nuxeo.org/trac/pub/browser/funkload/trunk/funkload/demo/
1353 .. _report: http://funkload.nuxeo.org/report-example.pdf
1354 .. _`GNU GPL`: http://www.gnu.org/licenses/licenses.html
1355 .. _`svn sources`: http://svn.nuxeo.org/pub/funkload/trunk/#egg=funkload-dev
1356 .. _trac: http://svn.nuxeo.org/trac/pub/report/12
1357 .. _doctest: http://docs.python.org/lib/module-doctest.html
1358
1359
1360 .. Local Variables:
1361 .. mode: rst
1362 .. End: