【问题标题】:Running django tests with selenium in docker在 docker 中使用 selenium 运行 django 测试
【发布时间】:2015-12-01 05:23:16
【问题描述】:

为了执行测试,我通常运行一个单独的容器:

docker-compose run --rm web /bin/bash

其中 web 是 django 的容器。我不时在 shell 中执行 py.test。

为了能够使用 django 从容器访问 selenium,并允许 selenium 容器中的浏览器访问 django 的 liveserver,我决定使用允许容器共享网络的“net”参数。所以我将它添加到 yml 中:

selenium:
    image: selenium/standalone-firefox
    net: "container:web"

不幸的是,这不起作用。我的 django 容器中没有看到 4444 端口。

只有当我指定一个自动生成的容器名称而不是 net:"container:web" 时,它才有效,例如 net:"container:project_web_run_1"

我也尝试使用 docker-compose up --no-depscommand 参数更改为 py.test functional_tests 而不是 docker-compose run --rm ....,但这也不起作用。

这是在容器中使用 selenium 的权利吗?

【问题讨论】:

    标签: python django selenium


    【解决方案1】:

    我刚刚为LiveServerTestCase 指定了host='web'。这是我的工作解决方案。

    test.py

    from django.test import LiveServerTestCase
    from selenium import webdriver
    from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
    
    class FunctionalTestCase(LiveServerTestCase):
        host = 'web'
        def setUp(self):
            self.browser = webdriver.Remote(
                command_executor="http://selenium:4444/wd/hub",
                desired_capabilities=DesiredCapabilities.FIREFOX
            )
    
        def test_user_registration(self):
            self.browser.get(self.live_server_url)
            self.assertIn('Django', self.browser.title)
    
        def tearDown(self):
            self.browser.close()
    

    docker-compose.yml

    version: '3'
    services:
      db:
        image: postgres
      web:
        build: .
        ports: 
          - "8000:8000"
        depends_on:
          - db
          - selenium
      selenium:
        image: selenium/standalone-firefox
    

    请记住,您必须在 docker 映像中安装 selenium 才能正常工作:

    $ docker-compose exec web bash
    > pip install selenium
    ...
    > pip freeze > ../requirements.txt
    > exit
    $ ...
    

    【讨论】:

      【解决方案2】:

      对于任何运行 pytest 的人,可能还有 pytest-splinter(Selenium 包装器)

      version: '3'
      services:
        db:
          image: postgres
        django:
          build: .
          ports: 
            - "8000:8000"
          depends_on:
            - db
            - selenium
        selenium:
          image: selenium/standalone-firefox-debug:latest
          ports:
            - "4444:4444"   # Selenium
            - "5900:5900"   # VNC 
      

      在您的根目录中定义一个 conftest.py 以使这些固定装置可用于您的所有测试

      import socket
      
      import pytest
      from pytest_django.live_server_helper import LiveServer
      
      
      @pytest.fixture(scope='session')
      def test_server() -> LiveServer:
          addr = socket.gethostbyname(socket.gethostname())
          server = LiveServer(addr)
          yield server
          server.stop()
      
      
      @pytest.fixture(autouse=True, scope='function')
      def _test_server_helper(request):
          """
          Configures test_server fixture so you don't have to mark
          tests with @pytest.mark.django_db
          """
          if "test_server" not in request.fixturenames:
              return
      
          request.getfixturevalue("transactional_db")
      
      
      # Settings below here are exclusive to splinter,
      # I'm just overriding the default browser fixture settings
      # If you just use selenium, no worries, just take note of the remote url and use 
      # it wherever you define your selenium browser
      
      @pytest.fixture(scope='session')
      def splinter_webdriver():
          return 'remote'
      
      @pytest.fixture(scope='session')
      def splinter_remote_url():
          return 'http://selenium:4444/wd/hub'
      
      

      不要忘记在配置文件中设置 ALLOWED_HOSTS:

      if env('USE_DOCKER') == 'yes':
          import socket
      
          ALLOWED_HOSTS = [socket.gethostbyname(socket.gethostname())]
      
      # or just
      ALLOWED_HOSTS = ['*']
      

      那就去测试吧!

      from django.urls import reverse
      
      
      def test_site_loads(browser, test_server):
          browser.visit(test_server.url + reverse('admin:index'))
      

      【讨论】:

      • 您能否澄清test_server 指的是什么以及它如何进入test_site_loads(browser, test_server) 的范围?它似乎与 conftest.py 中的定义有关,但它如何到达您的最后一个测试文件?
      【解决方案3】:

      在我的例子中,“web”容器只运行一个命令,即bash -c "sleep infinity"

      然后,我以docker-compose up -d 开始整个堆栈。

      然后,例如,我使用docker-compose exec web bash -c "cd /usr/src/app && tox"

      这样,我的web 主机可以从selenium 访问,始终使用相同的名称。

      使用docker-compose run web ... 每次都会生成新的(可预测的,但仍然是)主机名。

      【讨论】:

        【解决方案4】:

        这是我的做法。基本问题是 docker-compose run 会生成一个不同的主机名(project_container_run_x),其中 x 很难确定。我最终只是离开了IP地址。我还要确保 DEBUG 为 False,否则我会收到错误的请求。

        我正在像这样使用 StaticLiveServerTestCase:

        import os
        import socket
        
        os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = '0.0.0.0:8000'
        
        class IntegrationTests(StaticLiveServerTestCase):
            live_server_url = 'http://{}:8000'.format(
                socket.gethostbyname(socket.gethostname())
            )
        
            def setUp(self):
                settings.DEBUG = True
                self.browser = webdriver.Remote(
                    command_executor="http://selenium:4444/wd/hub",
                    desired_capabilities=DesiredCapabilities.CHROME
                )
        
            def tearDown(self):
                self.browser.quit()
                super().tearDown()
        
            def test_home(self):
                self.browser.get(self.live_server_url)
        

        我的 docker-compose 文件有这个用于 selenium 并扩展了 web 容器(运行 django 的地方)。端口 5900 对 VNC 开放。我喜欢将其隔离在 docker-compose.selenium.yml 之类的东西中

        version: '2'
        services:
          web:
            environment:
              SELENIUM_HOST: http://selenium:4444/wd/hub
              TEST_SELENIUM: 'yes'
            depends_on:
              - selenium
        
          selenium:
            image: selenium/standalone-chrome-debug
            ports:
              - "5900:5900"
        

        我可以运行类似的测试

        docker-compose run --rm web ./manage.py test
        

        所以我的 Web 容器正在通过“selenium”主机访问 selenium。 Selenium 然后通过动态确定的 IP 地址访问 Web 容器。

        另一个问题是使用“web”作为主机名很诱人。如果您的 docker-compose run 命令启动了一个单独的 Web 容器 - 这似乎可以工作。但是它不会使用您的测试数据库,因此不是一个很好的测试。

        【讨论】:

        • 您也可以在环境中设置liveserver URL,这样您就不必每次都在命令行中传递它,方法是设置DJANGO_LIVE_TEST_SERVER_ADDRESS
        猜你喜欢
        • 1970-01-01
        • 2023-03-23
        • 1970-01-01
        • 2020-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-12
        相关资源
        最近更新 更多