SoCo/SoCo — pull request #15 by KennethNielsen (2013-06-01 13:36:32+00:00)
Title: Unittest

I think it is about time to have this reviewed.

I was planning to make unit tests for all the methods in SoCo, but I think it is better for me to just get the stuff I already made in, and then I work on the rest in smaller chunks and other people can chip in too.

# Commit content
The merge request consist of three commits:
**8a59a4c**
This is the unit test framework/execution script. You use this to execute the unit tests and use the command line arguments to supply the necessary parameters to the tests and to control the output. The typical usage is as follows:
To execute all the unit tests we have:
execute_unittests.py --ip 192.168.0.110
There is also a convenience method to get a list of all the Sonos units
execute_unittests.py --list
To get unit test coverage statistics use the coverage argument;
execute_unittests.py --coverage
The modules argument is used to determine which classes (unit test modules) to execute and it works on both on the coverage and when running the unit tests. Currently there is only one module though, which means that "all", "soco" and the no modules argument default of "all" all does the same thing.
To get help
execute_unittests.py --help
There is also a color argument to colorize the output in bash terminals.

A few details about the implementation, that will probably raise questions:
**Lines 222-230**: It is not possible to pass arguments to the unit tests while executing them. The idea being that they should be self contained and therefore they should have all the data built in that they will need. However, that does not apply to SoCo becuase we will need to supply it with the ip at run time. Therefore, the execution script will call the method "init" in the unit test modules, if it exists, with a set of predefined arguments that can then be used for initialization.
**Automatic coverage calculation**: Yes, the automatic coverage calculations depends on a naming convention as follow:
1. Make a unit test case (class) for each method that you want to test
2. Name the class the same as the method except in camel case i.e. the test class for get_current_transport_info should be named GetCurrentTransportInfo.
3. If you want to make a unit test class for a hidden method "__*" then you should prefix the class name with the word "Private".
While non mandatory naming convention should generally be avoided I think they make sense here to easily get an overview of the coverage.

**01debd3**: This commit contains the first iteration unit tests for 38% of the methods in SoCo. There is an exception class (which will be moved to a dedicated exception file as soon as pull request 10 is merged. Then there is the init method mentioned above, a few convenience methods and one test case class per method). It also contains one commented out test case which awaits a fix I haven't gotten around to make.

# To add unit tests
To add unit tests for the methods in the SoCo class, simply write the required classes following the example of the existing classes.
To add unit tests for the methods in a new class do the following:
1. Make a new file in the unit test folder named "class_unittest.py" e.g. "soco_unittest.py"
2. (Defined an init method in it if necessary)
3. Add test case classes to this file. One test case class for each method
4. Make the execution framework aware of your unit test module by:
* Import the class and the unit test module
* Add an item to the UNITTEST_MODULES dict at line 190 in "execute_unittests.py". The added item should it self be a dictionary with items like this: {'name': 'SoCo', 'unittest_module': soco_unittest, 'class': soco.SoCo, 'arguments': {'ip': ARGS.ip}} where the arguments dict are the command line arguments required to run this module.
* Add you modules name to the help text in lines 53-55.

Any and all feedback is welcome.
\Kenneth