簡體   English   中英

在 docker 中使用 selenium 運行 django 測試

[英]Running django tests with selenium in docker

為了執行測試,我通常運行一個單獨的容器:

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 run --rm ....使用docker-compose run --rm .... docker-compose up --no-depscommand參數更改為py.test functional_tests但這也不起作用。

這是在容器中使用硒的權利嗎?

這是我如何做到的。 基本問題是 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 容器 - 這似乎可以工作。 但是它不會使用您的測試數據庫,因此不是一個很好的測試。

對於任何運行 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'))

我剛剛為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
$ ...

就我而言,“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 ...每次都會生成新的(可預測的,但仍然是)主機名。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM