channels: ChannelsLiveServerTestCase failing to load Apps

I can not complete the four part Channels tutorial. I can run the server and it works as expected, however the ChannelsLiveServerTestCase does not work. I have also tried using the standard LiveServerTestCase and it can run tests, however does not have the channels functionality as expected.

What I expected to happen vs. what actually happened This test from the django channels tutorial part four should pass: python manage.py test chat.tests

from channels.testing import ChannelsLiveServerTestCase
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.wait import WebDriverWait

class ChatTests(ChannelsLiveServerTestCase):
    serve_static = True  # emulate StaticLiveServerTestCase

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        try:
            # NOTE: Requires "chromedriver" binary to be installed in $PATH
            cls.driver = webdriver.Chrome()
        except:
            super().tearDownClass()
            raise

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()
        super().tearDownClass()

    def test_when_chat_message_posted_then_seen_by_everyone_in_same_room(self):
        try:
            self._enter_chat_room('room_1')

            self._open_new_window()
            self._enter_chat_room('room_1')

            self._switch_to_window(0)
            self._post_message('hello')
            WebDriverWait(self.driver, 2).until(lambda _:
                'hello' in self._chat_log_value,
                'Message was not received by window 1 from window 1')
            self._switch_to_window(1)
            WebDriverWait(self.driver, 2).until(lambda _:
                'hello' in self._chat_log_value,
                'Message was not received by window 2 from window 1')
        finally:
            self._close_all_new_windows()

    def test_when_chat_message_posted_then_not_seen_by_anyone_in_different_room(self):
        try:
            self._enter_chat_room('room_1')

            self._open_new_window()
            self._enter_chat_room('room_2')

            self._switch_to_window(0)
            self._post_message('hello')
            WebDriverWait(self.driver, 2).until(lambda _:
                'hello' in self._chat_log_value,
                'Message was not received by window 1 from window 1')

            self._switch_to_window(1)
            self._post_message('world')
            WebDriverWait(self.driver, 2).until(lambda _:
                'world' in self._chat_log_value,
                'Message was not received by window 2 from window 2')
            self.assertTrue('hello' not in self._chat_log_value,
                'Message was improperly received by window 2 from window 1')
        finally:
            self._close_all_new_windows()

    # === Utility ===

    def _enter_chat_room(self, room_name):
        self.driver.get(self.live_server_url + '/chat/')
        ActionChains(self.driver).send_keys(room_name + '\n').perform()
        WebDriverWait(self.driver, 2).until(lambda _:
            room_name in self.driver.current_url)

    def _open_new_window(self):
        self.driver.execute_script('window.open("about:blank", "_blank");')
        self.driver.switch_to_window(self.driver.window_handles[-1])

    def _close_all_new_windows(self):
        while len(self.driver.window_handles) > 1:
            self.driver.switch_to_window(self.driver.window_handles[-1])
            self.driver.execute_script('window.close();')
        if len(self.driver.window_handles) == 1:
            self.driver.switch_to_window(self.driver.window_handles[0])

    def _switch_to_window(self, window_index):
        self.driver.switch_to_window(self.driver.window_handles[window_index])

    def _post_message(self, message):
        ActionChains(self.driver).send_keys(message + '\n').perform()

    @property
    def _chat_log_value(self):
        return self.driver.find_element_by_css_selector('#chat-log').get_property('value')

However it is failing and giving the following trace

Creating test database for alias 'default'...
Destroying old test database for alias 'default'...
System check identified no issues (0 silenced).

DevTools listening on ws://127.0.0.1:55140/devtools/browser/6a3609e3-e493-47bc-85da-4259aac7b6da
ETraceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\spawn.py", line 105, in spawn_main
    exitcode = _main(fd)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\spawn.py", line 115, in _main
    self = reduction.pickle.load(from_parent)
EOFError: Ran out of input
ETraceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\spawn.py", line 105, in spawn_main
    exitcode = _main(fd)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\spawn.py", line 115, in _main
    self = reduction.pickle.load(from_parent)
EOFError: Ran out of input

======================================================================
ERROR: test_when_chat_message_posted_then_not_seen_by_anyone_in_different_room (chat.tests.ChatTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\django\test\testcases.py", line 202, in __call__
    self._pre_setup()
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\channels\testing\live.py", line 52, in _pre_setup
    self._server_process.start()
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\process.py", line 112, in start
    self._popen = self._Popen(self)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\context.py", line 223, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\context.py", line 322, in _Popen
    return Popen(process_obj)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
AttributeError: Can't pickle local object 'DaphneProcess.__init__.<locals>.<lambda>'

======================================================================
ERROR: test_when_chat_message_posted_then_seen_by_everyone_in_same_room (chat.tests.ChatTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\django\test\testcases.py", line 202, in __call__
    self._pre_setup()
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\channels\testing\live.py", line 52, in _pre_setup
    self._server_process.start()
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\process.py", line 112, in start
    self._popen = self._Popen(self)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\context.py", line 223, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\context.py", line 322, in _Popen
    return Popen(process_obj)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
AttributeError: Can't pickle local object 'DaphneProcess.__init__.<locals>.<lambda>'

----------------------------------------------------------------------
Ran 0 tests in 4.791s

FAILED (errors=2)
Destroying test database for alias 'default'...

OS, runtime environment and browser Windows 10 Django 1.11 and 2.0 chromewebdriver

What I have tried I have tried following this solution for a similar problem Which replaces import pickle with import dill as pickle in multiprocessing\reduction.py https://stackoverflow.com/questions/50016048/django-channels-2-with-selenium-test-failed

However I then get the following error

Creating test database for alias ‘default’… Destroying old test database for alias ‘default’… System check identified no issues (0 silenced).

DevTools listening on ws://127.0.0.1:55187/devtools/browser/28e3d4b6-a30c-44e9-a27f-d7e387471bd4
C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\daphne\server.py:13: UserWarning: Something has already installed a non-asyncio Twisted reactor. Attempting to uninstall it; you can fix this warning by importing daphne.server early in your codebase or finding the package that imports Twisted and importing it later on.
  UserWarning,
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\spawn.py", line 105, in spawn_main
    exitcode = _main(fd)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\multiprocessing\spawn.py", line 115, in _main
    self = reduction.pickle.load(from_parent)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\dill\_dill.py", line 304, in load
    obj = pik.load()
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\dill\_dill.py", line 465, in find_class
    return StockUnpickler.find_class(self, module, name)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\channels\auth.py", line 12, in <module>
    from django.contrib.auth.models import AnonymousUser
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\django\contrib\auth\models.py", line 2, in <module>
    from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\django\contrib\auth\base_user.py", line 47, in <module>
    class AbstractBaseUser(models.Model):
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\django\db\models\base.py", line 87, in __new__
    app_config = apps.get_containing_app_config(module)
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\django\apps\registry.py", line 249, in get_containing_app_config
    self.check_apps_ready()
  File "C:\Users\SubAtomicManiac\Anaconda5\envs\SoftEng\lib\site-packages\django\apps\registry.py", line 132, in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

I am completely new to channels and testing, and I couldn’t find a solution anywhere. I have tried with different versions of python/django/channels and I would get varying errors but none would work. Ideally I would like to get this to work with python 3.7, django 2.0+ and channels 2.0+ Thanks in advance

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 20 (6 by maintainers)

Most upvoted comments

I’m following the tutorial of channels (channels 3.03, Django 3.2.4, Python 3.8.7, macOS) and encountering the same issue. I, too, arrived to a similar error. Seems like the output from channels/testing/live.py cannot be properly handled.

Here’s my error message:

======================================================================
ERROR: test_when_chat_message_posted_then_seen_by_everyone_in_same_room (chat.tests.ChatTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/boonleng/.pyenv/versions/3.8.7/lib/python3.8/site-packages/django/test/testcases.py", line 272, in _setup_and_call
    self._pre_setup()
  File "/Users/boonleng/.pyenv/versions/3.8.7/lib/python3.8/site-packages/channels/testing/live.py", line 52, in _pre_setup
    self._server_process.start()
  File "/Users/boonleng/.pyenv/versions/3.8.7/lib/python3.8/multiprocessing/process.py", line 121, in start
    self._popen = self._Popen(self)
  File "/Users/boonleng/.pyenv/versions/3.8.7/lib/python3.8/multiprocessing/context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "/Users/boonleng/.pyenv/versions/3.8.7/lib/python3.8/multiprocessing/context.py", line 284, in _Popen
    return Popen(process_obj)
  File "/Users/boonleng/.pyenv/versions/3.8.7/lib/python3.8/multiprocessing/popen_spawn_posix.py", line 32, in __init__
    super().__init__(process_obj)
  File "/Users/boonleng/.pyenv/versions/3.8.7/lib/python3.8/multiprocessing/popen_fork.py", line 19, in __init__
    self._launch(process_obj)
  File "/Users/boonleng/.pyenv/versions/3.8.7/lib/python3.8/multiprocessing/popen_spawn_posix.py", line 47, in _launch
    reduction.dump(process_obj, fp)
  File "/Users/boonleng/.pyenv/versions/3.8.7/lib/python3.8/multiprocessing/reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
AttributeError: Can't pickle local object 'convert_exception_to_response.<locals>.inner'

----------------------------------------------------------------------

I’ve merged #1906 to enforce fork here, which at least lets test cases work on macOS. (We’ll need a fuller solution long-term, and for Windows support.)

Note pre-4.0 this requires the development version of daphne as well. See #1898

Andrew was pinged because this might be related to django/django based on my stack trace. Will need his input on whether an issue also needs to be raised over there.

Also based on previous comments I was under the impression you were investigating this.

I will refrain from pinging in the future.

I’m fighting with this error too (channels 3.0.1, django 3.1, py 3.9.1, macOS). I don’t have a solution, just observations: it looks like Daphne uses lambdas and reduction.py in the standard library multiprocessing tries to pickle them, but lambdas and nested functions can’t be pickled by the standard library’s pickler. They could be pickled by dill, but putting dill into reduction.py causes a circular import (dill imports from reduction.py). Anyway, my best guess so far is that replacing any lambdas or nested functions in Daphne with top level functions that can be pickled might solve it, though that looks to be a substantial project.