Visualising test results with PyTest and Philips Hue
— Python, Testing, Technology, Software Development — 4 min read
A couple of months ago I invested in a Philips Hue lamp and bridge, shortly after I got two Play lights for the back of the TV (in time for binging Game Of Thrones before the last season came out).
I like the idea of having the lighting controlled by changes such as the image on the TV, getting warmer in the evening or turning green and playing Smashmouth when an intruder breaks into the house.
My initial plan was to hook into the local Pokemon Go map and use the current team that owns the Pokemon Gym near our flat to control the colour of our lights — allowing the real world to be controlled by actions in the game and adding another level of augmentation to the players reality.
Unfortunately I rent so I’m not really in a position to set up something elaborate but I knew I wanted to play around with the lamp I had and at the time I had just finished using PyTest for configuration testing so thought a light based test reporter would be a good place to start.
Controlling your lights with Python
Philips Hue provides a really well implemented API that on following the developer introduction provided by Philips you learn how to register a new app locally and how to query and set the state of the devices and lights connected to the Phillips Hue Bridge.
Philips also provide a list of libraries for various languages on their developer website which is really useful.
As I’m working with PyTest I needed a library for Python and having reviewed the offerings on both Philips list and using the philips-hue
tag on Github I settled on PyHue as it provided the cleaned API for interacting with Philips Hue out of the bunch.
One issue with PyHue however is that running it on Python 3.7 resulted in a max recursion error on trying to set up the connection to bridge so I had to settle on running with Python 2.7 — I put this down to the fact that the last update to the library was 2013 but I am hoping to contribute code to make it Python 3 compatible.
In order to control your lights you need two pieces of information:
- The IP address of your Philips Hue Bridge
- A username for an app (which can be created following the Philips Developer tutorial)
You then create a new instance of pyhue.Bridge
which you can then query for the rooms and lights connected to the bridge.
An example script to connect to the bridge, and turn all lights off that are in the ‘Office’ room would look like:
Controlling the brightness and colour
Once you’ve got your light instance you can then change the brightness using light.bri
and the colour using X & Y values on a spectrum (which PyHue has a helper function for — rgb2xy(red, green, blue)
.
The brightness and colour value range are from 0 to 255 so setting a red light at full brightness would look like:
Building a test reporter in PyTest
You can create a test reporter in PyTest via two ways:
- Creating a new Python module with a
_reporter.py
which uses the PyTest hooks to add the reporter to the PyTest run - Adding the reporter to
conftest.py
(this is mostly for development purposes)
In both cases, the hooks you use to get data from the test run are:
pytest_collection_modifyitems(config, items)
— This is called at the start of the test run and is where you can access information on the tests that will be runpytest_runtest_logreport(report)
— This is called during the setup, running and teardown of the test (`report.when` tells you which stage is currently being executed,call
is the value for when the test is being run)
There are more hooks you can use to access the test report data at various stages but in order to show progress the two hooks mentioned will give you what you want.
Adding configuration values
In order to allow the user to provide values to configure the test reporter you need to create a _plugin.py
file with the following hooks:
pytest_addoption(parser)
— This is used to add the pytest command arguments so the values can be extractedpytest_configure(config)
— This is used to get the configuration values and then callconfig.pluginmanager.register()
with an instance of the test reporter class you created using the configuration valuespytest_unconfigure(config)
— This is used to callconfig.pluginmanager.unregister()
to remove the test reporter
Calculating test run progress
Getting the test run progress is pretty simple, you can set the total number of expected test cases to be run in the pytest_collection_modifyitems(config, items)
hook by calling len()
on the items
parameter.
Then in pytest_runtest_logreport(report)
check that the function’s executed during the actual run of the test via report.when == 'call'
and increment a test counter.
The call
phase is also when the test result is available so you can increment counters for passed, failed, skipped tests too.
If you’ve created a class for your test reporter and you set a total tests and executed tests class property you’re able to get the total progress.
Using the test run progress to set light parameters
If you’re logging the total executed, passed, failed, skipped test counts then you can apply this formula to get a 0–255 value which can then be used by PyHue to control the lights.
1int(255 * (executed_tests / total_tests))
Demo
Here’s a video of the test reporter in action:
You can find the test reporter code on my Gitlab or you can download the package into your project via pip.
1pip install pytest-hue
In order to run the test reporter you’ll need to configure the following values:
--hue-ip=XXX.XXX.XXX.XXX
— The IP address of Philips Hue Bridge--hue-username=username_to_use
— The username you created during the developer tutorial--hue-rooms=room_name
— A list of rooms to control
Next Steps
A couple of years back I experimented with Python and MIDI files and I think controlling my lights based on the MIDI data would be a nice little project to expand my Philips Hue knowledge.