PyOGP Package Unittests
Overview
Each package in the lib should have unit tests, which cover as much code as possible. The unit tests evaluate the integrity of the library code itself, in terms of apis, code paths, and dependencies.
Packages under unit test right now:
pyogp.lib.base pyogp.lib.client
Python test types
unittest
Unit tests are written as standard python unittest implementations. For more on this, see http://docs.python.org/library/unittest.html.
doctest
doctests are narrative sample uses of code, that may be run via various test wrappers. For more, see http://docs.python.org/library/doctest.html.
Running tests
nose
We use Nose! http://somethingaboutorange.com/mrl/projects/nose/0.11.1/
Buildout grabs the necessary module. If you are an enterprising soul, please download the nose source and install to your native python or virtualenv instance.
Nose Install Steps: # http://somethingaboutorange.com/mrl/projects/nose/nose-0.11.1.tar.gz # gzip -dc nose-0.11.1.tar.gz | tar xf - # cd nose-0.11.1 # python setup.py install
in buildout
After running buildout, there will be a bin/unittests script available. Simply run it, passing which package's unit tests to run...
bin/unittests --where=src/pyogp.lib.client/ bin/unittests --where=src/pyogp.lib.base/
per packages test runs
There is a test.py in each of pyogp.lib.*.tests. It works in a buildout context by adding to path all the necessary packages and dependencies, or works outside of buildout assuming your python path has all the necessary modules sourced.
To run it, simply:
cd pyogp/lib/base/tests python test.py
Pass test.py a file name, or to run all tests in the package, pass '..'.
Ensure the necessary modules are in your python instance's path:
Here's what the buildout generated nose test wrapper looks like on Enus' machine:
#!/Users/enus/svn/buildout/bin/python import sys sys.path[0:0] = [ '/Users/enus/svn/buildout/eggs/uuid-1.30-py2.5.egg', '/Users/enus/svn/buildout/eggs/indra.base-1.0-py2.5.egg', '/Users/enus/svn/buildout/eggs/eventlet-0.8.14-py2.5.egg', '/Users/enus/svn/buildout/eggs/wsgiref-0.1.2-py2.5.egg', '/Users/enus/svn/buildout/src/pyogp.lib.base', '/Users/enus/svn/buildout/eggs/nose-0.11.1-py2.5.egg', '/Users/enus/svn/buildout/eggs/WebOb-0.9.6.1-py2.5.egg', '/Users/enus/svn/buildout/eggs/elementtree-1.2.7_20070827_preview-py2.5.egg', '/Users/enus/svn/buildout/eggs/setuptools-0.6c9-py2.5.egg', '/Users/enus/svn/buildout/eggs/pyOpenSSL-0.9-py2.5-macosx-10.5-i386.egg', '/Users/enus/svn/buildout/eggs/greenlet-0.2-py2.5-macosx-10.5-i386.egg', '/Users/enus/svn/buildout/eggs/indra.util-1.0-py2.5.egg', ] import nose if __name__ == '__main__': nose.main(argv=['nose']+sys.argv[1:])
Evaluating test coverage
Nose has a great tie into the coverage module (http://nedbatchelder.com/code/modules/rees-coverage.html), which evaluates code coverage by our tests. Buildout automatically installs the necessary module, or, you can install it to your python instance via "easy_install coverage".
To run the unittests via a buildout instance, add the following flags (making sure package names match up):
--with-coverage --cover-package=pyogp.lib.client
For more on the nose test wrapper, see bin/unittests -h.
Code Coverage
Currently, coverage of code by unittest is OK, but, we need to improve it!
pyogp.lib.client
Current coverage:
[11:32:17] [enus@sune] buildout$ bin/unittests --where=src/pyogp.lib.client/ --with-coverage --cover-package=pyogp.lib.client Name Stmts Exec Cover Missing ------------------------------------------------------------- pyogp.lib.client 1 1 100% pyogp.lib.client.agent 513 164 31% 35-49, 71, 82, 179-180, 213, 216, 222-239, 272, 281-303, 311-331, 336-345, 350-359, 365-431, 437-446, 452-457, 477-486, 496-533, 552-570, 575-580, 586-587, 593, 600-615, 620-632, 637-644, 649, 658-674, 679-700, 705-746, 751-757, 762-787, 792-804, 818-872, 881-925, 930-953, 967-980, 986-1017, 1024-1044, 1052-1068, 1073, 1080-1086, 1090-1093, 1098-1101, 1105, 1109-1112, 1117-1119 pyogp.lib.client.appearance 151 76 50% 76-83, 89-97, 122-135, 151-162, 165, 171, 179-183, 194-199, 216-226, 234-249, 257-280, 294-310, 335, 341-347, 354-355 pyogp.lib.client.assets 125 30 24% 58, 68-123, 145-168, 174, 177, 185-192, 202-211, 215-217, 222-231, 234-261 pyogp.lib.client.event_queue 153 90 58% 31, 39, 64, 73, 104, 107-109, 118-125, 136-149, 173, 179, 184-215, 220-235, 248-273 pyogp.lib.client.event_system 89 71 79% 43, 60-67, 82-84, 173-174, 184-185, 193-200, 205, 210 pyogp.lib.client.exc 136 78 57% 36, 42, 45, 57-60, 64, 73, 76, 86-90, 94, 116, 119, 128, 131, 141-142, 145, 160-161, 164, 173-174, 177, 186-187, 190, 199-200, 203, 212-213, 216, 225-226, 229, 238-239, 242, 261, 273, 285, 302, 305, 317, 330, 333, 345, 348, 356, 359, 367, 370 pyogp.lib.client.groups 243 54 22% 65-79, 85-90, 97-111, 116-130, 135-144, 149-156, 174-205, 210-215, 221-224, 229-236, 241, 246-252, 262-273, 278-287, 292-310, 315, 320, 325-329, 333-339, 347-359, 364, 369-375, 380-382, 387-404, 424-451, 469-477, 484-488, 492, 496-520, 524-527 pyogp.lib.client.inventory 495 181 36% 73-80, 84, 88, 93-152, 157-164, 173-180, 191-193, 199-202, 227, 243, 275-277, 295-302, 312, 320-322, 332-338, 350, 362, 373, 378-384, 389-391, 399-408, 417-431, 436-468, 473-480, 522, 559-560, 567-572, 577, 582, 587, 592, 599-601, 606-630, 635-659, 664-697, 702-705, 710-742, 749, 754, 759, 764-775, 780, 784-812, 816-867, 897, 902-909, 914, 924-933, 938, 948-956, 1021-1027, 1036-1040, 1046-1063, 1075-1104, 1109-1150 pyogp.lib.client.login 205 176 85% 111, 129, 150, 171, 201, 210, 225-226, 234, 281-283, 293, 300-301, 308-313, 341, 343, 347, 361, 370, 374-377, 389, 406, 433 pyogp.lib.client.objects 612 276 45% 114, 120-132, 143, 159-190, 200, 207, 212-220, 225-227, 235-239, 244-257, 262-284, 289-294, 298-303, 329-332, 340, 354, 357, 367-376, 382-391, 425-461, 466-633, 639-663, 691-693, 729-859, 907-908, 919-967, 971-973, 977-1014, 1037-1067, 1173, 1183-1195, 1203-1205, 1213-1215, 1223-1225, 1233-1235, 1242-1244, 1251-1253, 1260, 1268-1276, 1283, 1291-1299, 1304, 1309-1323, 1328-1344, 1351, 1358-1365, 1372, 1379-1386 pyogp.lib.client.parcel 372 69 18% 99-112, 122-127, 132-185, 190-212, 219-234, 239-279, 284-299, 304-307, 311, 315, 319, 325-328, 333-338, 343-359, 364-376, 381-389, 394-412, 417-424, 429-447, 452-456, 462, 467-482, 489, 521, 554, 587, 615, 642, 670, 696-699, 704-713, 721-723, 747-750, 755-763, 768-787, 797-873, 878-882, 889, 921, 945, 978, 1006, 1030, 1051, 1083, 1107, 1139 pyogp.lib.client.permissions 23 18 78% 57-61 pyogp.lib.client.region 259 91 35% 34, 40-41, 43, 78, 85, 96, 189-195, 199, 223-229, 237-240, 245-250, 255-272, 277-285, 289-315, 321-331, 336-351, 356-361, 366-367, 373-385, 390-396, 401-407, 412-416, 433-448, 453-460, 465-472, 477-514, 519-523, 528-529, 535-565, 570, 575, 580-586, 597-620, 623 pyogp.lib.client.settings 67 55 82% 146-155, 178-179 pyogp.lib.client.visualparams 502 495 98% 42-44, 50-53 ------------------------------------------------------------- TOTAL 3946 1925 48% ---------------------------------------------------------------------- Ran 94 tests in 14.455s FAILED (errors=1)
pyogp.lib.base
Nice coverage!
[11:32:40] [enus@sune] buildout$ bin/unittests --where=src/pyogp.lib.base/ --with-coverage --cover-package=pyogp.lib.base Name Stmts Exec Cover Missing ---------------------------------------------------------------------- pyogp.lib.base 1 1 100% pyogp.lib.base.datatypes 106 73 68% 45, 49, 53, 72, 75, 80, 88-91, 107, 111, 115, 119, 136-141, 150, 153, 158, 184-189, 208, 213, 222-225, 230-232 pyogp.lib.base.exc 136 77 56% 33, 36, 42, 45, 57-60, 64, 73, 76, 86-90, 94, 116, 119, 128, 131, 141-142, 145, 160-161, 164, 173-174, 177, 186-187, 190, 199-200, 203, 212-213, 216, 225-226, 229, 238-239, 242, 261, 273, 285, 302, 305, 317, 330, 333, 345, 348, 356, 359, 367, 370 pyogp.lib.base.message 1 1 100% pyogp.lib.base.message.circuit 84 69 82% 39, 78-83, 91, 98-104, 134, 149-150, 154 pyogp.lib.base.message.data 4 4 100% pyogp.lib.base.message.data_packer 63 48 76% 66, 69-70, 73-75, 78, 81, 84-87, 92, 99, 101 pyogp.lib.base.message.data_unpacker 65 57 87% 76-80, 83-84, 91, 94, 100 pyogp.lib.base.message.llsd_builder 39 38 97% 34 pyogp.lib.base.message.message 63 42 66% 35-36, 43-44, 109-110, 114, 119-136, 141 pyogp.lib.base.message.message_handler 44 29 65% 38, 47-49, 60, 75-78, 88-90, 93, 97, 100-102, 106 pyogp.lib.base.message.msgtypes 83 76 91% 45-47, 118, 125, 127, 143 pyogp.lib.base.message.template 133 105 78% 46, 63, 71, 84, 87-92, 98, 101, 105, 116, 119, 121, 145, 148, 151, 154, 187, 190, 196, 199, 202, 205, 208, 211, 214 pyogp.lib.base.message.template_dict 58 52 89% 49-52, 100, 106 pyogp.lib.base.message.template_parser 228 187 82% 172-173, 177, 223, 252, 266-278, 281-294, 297-305, 309-317, 320 pyogp.lib.base.message.udpdeserializer 180 139 77% 52, 76-78, 116-125, 132, 138, 145-147, 170, 175, 184, 193, 197, 220-230, 240, 262, 274-275, 296-297, 308-315, 321-323, 335 pyogp.lib.base.message.udpdispatcher 149 108 72% 80, 111, 124-130, 135, 141, 147, 164, 173, 178, 190, 192, 203-211, 220-224, 242-255, 281, 287-288, 297-301, 305 pyogp.lib.base.message.udpserializer 66 57 86% 72, 89, 110-111, 131, 138, 143-147 pyogp.lib.base.network 1 1 100% pyogp.lib.base.network.net 27 14 51% 31, 35-38, 41-50, 66 pyogp.lib.base.settings 67 45 67% 146-155, 167-198 pyogp.lib.base.utilities 1 1 100% pyogp.lib.base.utilities.events 35 17 48% 36-38, 43-51, 55-65, 69, 73-74, 78 pyogp.lib.base.utilities.helpers 107 45 42% 48, 54-58, 64-71, 77-81, 87-100, 106-119, 125-128, 136, 150, 156, 162, 187, 204, 208, 213, 267-268, 270, 275-276, 287-292, 296-305, 309 ---------------------------------------------------------------------- TOTAL 1741 1286 73% ---------------------------------------------------------------------- Ran 71 tests in 17.255s OK