0

I'm trying to make tests on a helper function that reacts on import success or not.

The success test is working but not the failing one, do you know why ?

The helper : homeassistant/components/owntracks/helper.py

"""Helper for OwnTracks."""
try:
    import nacl
except ImportError:
    nacl = None

import logging

_LOGGER = logging.getLogger(__name__)


def supports_encryption() -> bool:
    """Test if we support encryption."""
    _LOGGER.info(nacl)
    return nacl is not None

My test : tests/components/owntracks/test_helper.py

"""Test the owntracks helper."""
from unittest.mock import patch
import pytest
import logging

from homeassistant.components.owntracks.helper import supports_encryption

_LOGGER = logging.getLogger(__name__)

@pytest.fixture(name="nacl_imported")
def mock_nacl_imported():
    """Mock a successful import."""
    with patch("homeassistant.components.owntracks.helper.nacl"):
        yield


@pytest.fixture(name="nacl_not_imported")
def mock_nacl_not_imported():
    """Mock non successful import."""
    with patch("homeassistant.components.owntracks.helper.nacl") as mock_import:
        mock_import.return_value = ImportError()
        yield mock_import


def test_supports_encryption(nacl_imported):
    """Test if env supports encryption."""
    _LOGGER.info(supports_encryption())
    assert supports_encryption()


def test_supports_encryption_failed(nacl_not_imported):
    """Test if env does not support encryption."""
    _LOGGER.info(supports_encryption())
    assert not supports_encryption()

Also tried:

    with patch("homeassistant.components.owntracks.helper.nacl", return_value=None):
        yield

AND

    with patch("homeassistant.components.owntracks.helper.nacl", side_effect=ImportError()):
        yield

Test logs :

 py.test tests/components/owntracks/test_helper.py
Test session starts (platform: linux, Python 3.7.4, pytest 5.2.2, pytest-sugar 0.9.2)
rootdir: /home/quentin.pollet@sglk.local/Documents/home-assistant, inifile: setup.cfg
plugins: timeout-1.3.3, cov-2.8.1, requests-mock-1.7.0, aiohttp-0.3.0, sugar-0.9.2
collecting ... 
 tests/components/owntracks/test_helper.py ✓                                       50% █████     

―――――――――――――――――――――――――――――――― test_supports_encryption_failed ――――――――――――――――――――――――――――――――

nacl_not_imported = <MagicMock name='nacl' id='139733318227280'>

    def test_supports_encryption_failed(nacl_not_imported):
        """Test if env does not support encryption."""
        _LOGGER.info(supports_encryption())
>       assert not supports_encryption()
E       assert not True
E        +  where True = supports_encryption()

tests/components/owntracks/test_helper.py:34: AssertionError
------------------------------------- Captured stderr call --------------------------------------
INFO:homeassistant.components.owntracks.helper:<MagicMock name='nacl' id='139733318227280'>
INFO:tests.components.owntracks.test_helper:True
INFO:homeassistant.components.owntracks.helper:<MagicMock name='nacl' id='139733318227280'>
--------------------------------------- Captured log call ---------------------------------------
INFO     homeassistant.components.owntracks.helper:helper.py:14 <MagicMock name='nacl' id='139733318227280'>
INFO     tests.components.owntracks.test_helper:test_helper.py:33 True
INFO     homeassistant.components.owntracks.helper:helper.py:14 <MagicMock name='nacl' id='139733318227280'>

 tests/components/owntracks/test_helper.py ⨯                                      100% ██████████

Results (0.15s):
       1 passed
       1 failed
         - tests/components/owntracks/test_helper.py:31 test_supports_encryption_failed

I'm new at Python, but motivated, be nice ;)

Quentame
  • 254
  • 1
  • 4
  • 13

1 Answers1

0

From your given details, it is cleared that the method supports_encryption() will check the import status of nacl. If not installed, then it would change the nacl value to False. Moreover, after that, you are verifying the value of nacl with True/False (nacl is not None will return True, if it is not None).

The return value of supports_encryption() will always be True.

In test method test_supports_encryption_failed(), you used assert not supports_encryption(), that's why it is failing.

For mocking the imports value, use the below:-

$ pytest -vsx test_11.py
platform linux2 -- Python 2.7.15+, pytest-4.6.6, py-1.8.0, pluggy-0.13.0 -- /usr/bin/python
cachedir: .pytest_cache
metadata: {'Python': '2.7.15+', 'Platform': 'Linux-4.15.0-60-generic-x86_64-with-Ubuntu-18.04-bionic', 'Packages': {'py': '1.8.0', 'pytest': '4.6.6', 'pluggy': '0.13.0'}, 'Plugins': {u'html': u'1.22.0', u'metadata': u'1.8.0'}}
rootdir: /home/nikhilesh
plugins: html-1.22.0, metadata-1.8.0
collected 2 items                                                                                                                                                      

test_11.py::test_success ('Value is ', <module 'os' from '/usr/lib/python2.7/os.pyc'>)
PASSED
test_11.py::test_fail ('Value is ', None)
PASSED

======================================================================= 2 passed in 0.07 seconds =======================================================================
$ cat test_11.py 
import utility
import mock



def test_success():
    print("Value is ", utility.os)



@mock.patch("utility.os", return_value = None)
def test_fail(mock_os):
    print("Value is ", utility.os.return_value)
nikhilesh_koshti
  • 393
  • 1
  • 10
  • Hi ! Thanks for your answer :) But if I can correct the value of `nacl` will turn to None, not False ? I don't get why using `not supports_encryption()` is making my test fail. I should use `supports_encryption() == False` ? I think it's the same. Also, my goal is to test `supports_encryption()`, not the value of `nacl`. I will also test using `@mock.patch` instead of `@pytest.fixture`. – Quentame Nov 04 '19 at 09:10