Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it easier to run mock services in place of real ones #81

Open
hadess opened this issue Jul 29, 2021 · 4 comments
Open

Make it easier to run mock services in place of real ones #81

hadess opened this issue Jul 29, 2021 · 4 comments
Labels

Comments

@hadess
Copy link
Contributor

hadess commented Jul 29, 2021

A lot of the code in python-dbusmock assumes that the developer will want to create a fake bus, along with fake services to specifically run a test case.

This makes it difficult to reuse the templates to create replacement for real service, which one would run in place of the real service, for the purpose of testing an interactive UI.

For example, having a run-mock-upower.py with a menu of different scenarios would make it a good replacement for the hard-coded tests rigged into GNOME's Power panel which don't really test the upower communication.

@martinpitt
Copy link
Owner

Right now you can do this on the CLI, as described in README:

sudo systemctl stop upower
sudo python3 -m dbusmock -t upower

Then upower --dump shows the mocked devices, and the mock shows the called methods. By calling methods on the Mock interface, you can also change the mock on the fly.

Do you have some ideas/suggestions how to make this more convenient? Merci !

@hadess
Copy link
Contributor Author

hadess commented Aug 3, 2021

I was actually looking for something which wouldn't require launching the service, waiting for it to become available, attaching to it, and calling out to change the default mocked values separately, all things that the testcase class code does.

The idea being that this (single file python) live test helper would probably stop upower, launch a mock upower, modify the mock upower depending on the use case being tested, and when done stop the mock upower, and relaunch the real one.

@martinpitt
Copy link
Owner

The systemctl stop upower is actually not necessary, as dbusmock.py uses allow_replacement=True and replace_existing=True. You can also specify parameters in JSON form with -p. Once stopping the mock, D-Bus activation will just bring back the real upower.service.

So the CLI cares about all the bits in your list. The one thing that it can't do is to tell you when it's ready, as it just runs synchronous. There's two main ways here: (1) it could grow a --background option, to fork itself into the background once the setup is done, and then you kill that pid (but it's a bit fiddly to tell you which pid that is), or it could accept an argv vector after -- and just run that after the setup. This could be something like sudo python3 -m dbusmock -t upower -- bash -i.

Would that work for you? Any other ideas?

@hadess
Copy link
Contributor Author

hadess commented Aug 31, 2021

The systemctl stop upower is actually not necessary, as dbusmock.py uses allow_replacement=True and replace_existing=True. You can also specify parameters in JSON form with -p. Once stopping the mock, D-Bus activation will just bring back the real upower.service.

That works, although passing parameters as JSON is unlikely to be something human-parseable before long.

So the CLI cares about all the bits in your list. The one thing that it can't do is to tell you when it's ready, as it just runs synchronous. There's two main ways here: (1) it could grow a --background option, to fork itself into the background once the setup is done, and then you kill that pid (but it's a bit fiddly to tell you which pid that is), or it could accept an argv vector after -- and just run that after the setup. This could be something like sudo python3 -m dbusmock -t upower -- bash -i.

I don't actually care about the server being ready per-se, I care about it being available to feed commands.

Would that work for you? Any other ideas?

This is what I'd like to be able to have:

  • one command to run the fake upower
  • fake upower is interactive, and has a simple menu, eg. something to plug/unplug the power cord, change the battery level

parsing info from template to arguments is duplicated between dbusmock/__main__.py and testcase.spawn_server_template, and calls out deep inside the testcase class to dbusmock.testcase.DBusTestCase.get_dbus() which is a bit weird.

I would expect most of the code below to disappear into function calls.

#!/usr/bin/python3

import dbusmock.mockobject
import dbusmock.testcase

if __name__ == '__main__':
    import dbus.service
    import dbus.mainloop.glib
    from gi.repository import GLib

    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    module = dbusmock.mockobject.load_module("upower")
    name = module.BUS_NAME
    path = module.MAIN_OBJ
    system_bus = module.SYSTEM_BUS

    main_loop = GLib.MainLoop()
    bus = dbusmock.testcase.DBusTestCase.get_dbus(system_bus)

    # quit mock when the bus is going down
    bus.add_signal_receiver(main_loop.quit, signal_name='Disconnected',
                            path='/org/freedesktop/DBus/Local',
                            dbus_interface='org.freedesktop.DBus.Local')

    bus_name = dbus.service.BusName(module.BUS_NAME,
                                    dbusmock.testcase.DBusTestCase.get_dbus(module.BUS_NAME),
                                    allow_replacement=True,
                                    replace_existing=True,
                                    do_not_queue=True)

    main_object = dbusmock.mockobject.DBusMockObject(bus_name, module.MAIN_OBJ,
                                                     module.MAIN_IFACE, {}, 
                                                     None,
                                                     False)

    dbusmock.mockobject.objects[module.MAIN_OBJ] = main_object

    # FIXME Wait here
    # FIXME Setup defaults
    # FIXME Setup menu

    main_loop.run()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants