pytest-homeassistant-custom-component icon indicating copy to clipboard operation
pytest-homeassistant-custom-component copied to clipboard

pytest_socket.SocketBlockedError: A test tried to use socket.socket.

Open fishy242 opened this issue 2 years ago • 11 comments

Hi,

I shall say at the very beginning, I am new to the home assistant custom component development and new to python too, so I think I get something missing but I cannot find any result from google.

What I have done so far is just clone this repo, setup a venv by python -m venv venv, activate the venv and then to pip install pytest-homeassistant-custom-componet. Every things look OK so far. But when I try to run pytest in this repo, I get the following error

――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― ERROR at setup of test_sensor ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――

fixturedef = <FixtureDef argname='event_loop' scope='function' baseid=''>, request = <SubRequest 'event_loop' for <Function test_sensor>>

    @pytest.hookimpl(hookwrapper=True)
    def pytest_fixture_setup(
        fixturedef: FixtureDef, request: SubRequest
    ) -> Optional[object]:
        """Adjust the event loop policy when an event loop is produced."""
        if fixturedef.argname == "event_loop":
            outcome = yield
>           loop = outcome.get_result()

venv\lib\site-packages\pytest_asyncio\plugin.py:399:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv\lib\site-packages\pytest_asyncio\plugin.py:513: in event_loop
    loop = asyncio.get_event_loop_policy().new_event_loop()
venv\lib\site-packages\homeassistant\runner.py:104: in new_event_loop
    loop: asyncio.AbstractEventLoop = super().new_event_loop()
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2800.0_x64__qbz5n2kfra8p0\lib\asyncio\events.py:673: in new_event_loop
    return self._loop_factory()
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2800.0_x64__qbz5n2kfra8p0\lib\asyncio\windows_events.py:315: in __init__
    super().__init__(proactor)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2800.0_x64__qbz5n2kfra8p0\lib\asyncio\proactor_events.py:636: in __init__
    self._make_self_pipe()
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2800.0_x64__qbz5n2kfra8p0\lib\asyncio\proactor_events.py:767: in _make_self_pipe
    self._ssock, self._csock = socket.socketpair()
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2800.0_x64__qbz5n2kfra8p0\lib\socket.py:630: in socketpair
    lsock = socket(family, type, proto)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

cls = <class 'pytest_socket.disable_socket.<locals>.GuardedSocket'>, family = <AddressFamily.AF_INET: 2>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, fileno = None
    def __new__(cls, family=-1, type=-1, proto=-1, fileno=None):
        if _is_unix_socket(family) and allow_unix_socket:
            return super().__new__(cls, family, type, proto, fileno)

>       raise SocketBlockedError()
E       pytest_socket.SocketBlockedError: A test tried to use socket.socket.

venv\lib\site-packages\pytest_socket.py:80: SocketBlockedError

I get the same error even on my dummy test which just contain assert(True). Apparently I didn't try to open any socket. How can I get rid of this issue?

Your help and advice would be much appreciated. Thanks!

fishy242 avatar Apr 04 '23 08:04 fishy242

See #96, which is probably related.

Are you defining any fixtures in your test? It looks like it is failing during setup of the test.

MatthewFlamm avatar Apr 04 '23 12:04 MatthewFlamm

@MatthewFlamm, hello.

This issue is relevant for tests in https://github.com/MatthewFlamm/pytest-homeassistant-custom-component/tree/master/tests without any modifications at Windows machines. Linux machines is not affected.

Looks like Windows is using AF_INET socket for creating asyncio, so https://github.com/MatthewFlamm/pytest-homeassistant-custom-component/blob/ee2dc5641df608d47bbbdaf9e2fca59398f0d8b4/src/pytest_homeassistant_custom_component/plugins.py#L153 could not allow it. (after commenting just this line all works well by obvious reason)

IATkachenko avatar Apr 04 '23 14:04 IATkachenko

If this is indeed a Windows difference, homeassistant core does not support or test on Windows, so this is use case is unsupported. You may need to use a fixture to enable the needed socket, but I am not familiar with this.

MatthewFlamm avatar Apr 04 '23 14:04 MatthewFlamm

The problem is not in HomeAssistant code base, but in pytest-soket + asyncio for Windows... pytest-homeassistant-custom-component is blocking socket usage for tests, like HA https://github.com/home-assistant/core/blob/28d85bc405136cfeec3dcebaeb8705102aaa2294/tests/conftest.py#L149 ,so any usage of hass in tests will cause SocketBlockedError at Windows machines.

Special fixture for enabling socket looks promising, but is should be loaded in hass fixture to avoid unnecessary calls or test arguments...

IATkachenko avatar Apr 04 '23 14:04 IATkachenko

This package simply extracts the testing from homeassistant core with very light modifications for ease of use. If running in Windows isn't supported in homeassistant core, then it won't be supported here either. We don't mess with hass fixture in this package for this reason.

MatthewFlamm avatar Apr 04 '23 15:04 MatthewFlamm

If Windows is not suppose to work, any advice on the dev environment? Simply wsl? Or inside the devcontainer of the official home assistance code dev environment? The file structure come out from cookiecutter template seems not so ideal to use in Home assistant core devcontainer.

Thanks for pointing the right direction to beginner as me:)

fishy242 avatar Apr 04 '23 20:04 fishy242

@fishy242, for tests from Windows I'm using dev container like this (is not advice, but it is my way to run tests while using Windows):

FROM python:3.9.10
ENV PIP_DISABLE_ROOT_WARNING=1
RUN python -m pip install --upgrade pip
COPY requirements_test.txt requirements.txt
RUN pip install -r requirements.txt
VOLUME /app
WORKDIR /app
ENV NO_COLOR=yes_please
ENV LANG=C
CMD ["python", "-m", "pytest"]

and using project root as /app volume in the container.

IATkachenko avatar Apr 05 '23 13:04 IATkachenko

Now I do coding and testing in WSL, I think that’s good enough for me at this moment.

Thanks all the help from here!

fishy242 avatar Apr 06 '23 12:04 fishy242

I'm stuck with this error as well... on MacOS though...

tests/components/lightener/test_config_flow.py Error attempting to connect to extension communication socket[vscode-pytest]: A test tried to use socket.socket.
If you are on a Windows machine, this error may be occurring if any of your tests clear environment variables as they are required to communicate with the extension. Please reference https://docs.pytest.org/en/stable/how-to/monkeypatch.html#monkeypatching-environment-variablesfor the correct way to clear environment variables during testing.

fredck avatar Nov 13 '23 18:11 fredck

I have run into this issue with a DevContainer on Windows. The tests run from the CLI but fail in VS Code. The solution for me was to comment out the code which blocks sockets.

I've created a branch which you can test by replacing the pytest-homeassistant-custom-component requirement in your requirements file with:

pytest-homeassistant-custom-component @ git+https://github.com/matthewturner/pytest-homeassistant-custom-component@remove-socket-blocking

I'm not sure what the permanent solution to this would be.

matthewturner avatar Feb 17 '24 10:02 matthewturner

Also happening within a remote dev-container running in docker on ubuntu.

Workaround for me is the following conftest.py class in my tests folder:

from pytest_socket import enable_socket, disable_socket, socket_allow_hosts
import pytest


@pytest.hookimpl(trylast=True)
def pytest_runtest_setup():
    enable_socket()
    socket_allow_hosts(["127.0.0.1", "localhost", "::1"], allow_unix_socket=True)

There is an update on the original issue from vscode: https://github.com/microsoft/vscode-python/issues/22383

Xyaren avatar Apr 18 '24 19:04 Xyaren