(Title was: \"How to write a unit test for a DBUS service written in Python?\")
I\'ve started to write a DBUS service using dbus-python, but I\'m having trouble writ
With some help from Ali A's post, I have managed to solve my problem. The blocking event loop needed to be launched into a separate process, so that it can listen for events without blocking the test.
Please be aware my question title contained some incorrect terminology, I was trying to write a functional test, as opposed to a unit test. I was aware of the distinction, but didn't realise my mistake until later.
I've adjusted the example in my question. It loosely resembles the "test_pidavim.py" example, but uses an import for "dbus.glib" to handle the glib loop dependencies instead of coding in all the DBusGMainLoop stuff:
import unittest
import os
import sys
import subprocess
import time
import dbus
import dbus.service
import dbus.glib
import gobject
class MyDBUSService(dbus.service.Object):
def __init__(self):
bus_name = dbus.service.BusName('test.helloservice', bus = dbus.SessionBus())
dbus.service.Object.__init__(self, bus_name, '/test/helloservice')
def listen(self):
loop = gobject.MainLoop()
loop.run()
@dbus.service.method('test.helloservice')
def hello(self):
return "Hello World!"
class BaseTestCase(unittest.TestCase):
def setUp(self):
env = os.environ.copy()
self.p = subprocess.Popen(['python', './dbus_practice.py', 'server'], env=env)
# Wait for the service to become available
time.sleep(1)
assert self.p.stdout == None
assert self.p.stderr == None
def testHelloService(self):
bus = dbus.SessionBus()
helloservice = bus.get_object('test.helloservice', '/test/helloservice')
hello = helloservice.get_dbus_method('hello', 'test.helloservice')
assert hello() == "Hello World!"
def tearDown(self):
# terminate() not supported in Python 2.5
#self.p.terminate()
os.kill(self.p.pid, 15)
if __name__ == '__main__':
arg = ""
if len(sys.argv) > 1:
arg = sys.argv[1]
if arg == "server":
myservice = MyDBUSService()
myservice.listen()
else:
unittest.main()