Notify api cannot be used in tests
Closed this issue ยท 2 comments
I have a test that calls the notify api on appdaemon apps such as:
class ExampleApp(hass.Hass):
def initialize(self):
self.notify(message="test", name="html5")
This does not work in the tests because the AD attribute never get instantiated and raises an AttributeError here:
def hass_check(func):
def func_wrapper(*args, **kwargs):
self = args[0]
if not self.AD.get_plugin(self._get_namespace(**kwargs)).reading_messages:
self.AD.log("WARNING", "Attempt to call Home Assistant while disconnected: {}".format(func))
return lambda *args: None
else:
return func(*args, **kwargs)
return (func_wrapper)
I could certainly overwrite the notify method to call self.call_service
directly, but it seems like it would be better to test against the current appdaemon API. I was able to monkey patch the AD attribute, but I then ran into another issue with the app's namespace never being set. I had to call app.set_namespace("default")
to get past that, but it seems these should be handled in the test initialization.
Hi,
Thanks for reporting the issue ๐
The current design of assert_that
does not allow to directly perform assertions on all the helper methods of the Hass
class. In all my projects calling services and turning on/off entities represents 90% of the work being done so I didn't try to find a way to nicely integrate the other features of the Appdaemon framework.
That being said, there is a way to test for helper methods, they just need to first be patched. Then, all patched methods of the Hass
object can be accessed via an injectable pytest fixture: hass_functions
. It's briefly mentioned in the doc.
I just patched the notify
function, so using hass_functions
with notify
will be working after you update the appdaemontestframework
.
In practice, this is how it will look like:
class ExampleApp(hass.Hass):
def initialize(self):
pass
def do_something_that_calls_notify(self):
...
self.notify(message="test", name="html5")
...
@automation_fixture(ExampleApp)
def example_app():
pass
def test_notify(given_that, example_app, hass_functions):
example_app.do_something_that_calls_notify()
hass_functions['notify'].assert_called_with(message="test", name="html5")
I also added a test to confirm the functionality is working: Test Extra Hass Functions
If you need to call it during initialize
like in your example, no problem simply call initialize
again in your test. The @mock_automation
fixture is taking care of cleaning the mocks calls that might have been performed during the initialization phase so that you end up with a clean state at the beginning of the test. Again, in practice:
class ExampleApp(hass.Hass):
def initialize(self):
self.notify(message="during init", name="html5")
@automation_fixture(ExampleApp)
def example_app():
pass
def test_notify_during_init(given_that, example_app, hass_functions):
hass_functions['notify'].assert_not_called()
example_app.initialize()
hass_functions['notify'].assert_called_with(message="during init", name="html5")
Update to version 2.3.2
and let me know how it's working out for you ๐
Thanks, that should work for what I need.