Selenium не использует тестовую базу данных во время функциональных тестов Django в Docker или не может получить доступ Python

Программы на Python
Ответить
Anonymous
 Selenium не использует тестовую базу данных во время функциональных тестов Django в Docker или не может получить доступ

Сообщение Anonymous »

Проблема
Мой браузер Selenium Chrome не может получить доступ к моему веб-приложению Django, когда оно использует тестовую базу данных Django. Djangos StaticLiveServerTestCase создает случайные порты при создании тестовых баз данных. С помощью Docker я могу открыть только жестко запрограммированные порты:
host_ip = socket.gethostbyname(socket.gethostname())
host_port = urlparse(self.live_server_url).port
self.live_server_url = f"http://{host_ip}:{host_port}"

# results in
# selenium.common.exceptions.WebDriverException: Message: unknown error: net::ERR_CONNECTION_REFUSED

Я могу установить один фиксированный порт для своих тестов. Но потом они жалуются, что порт уже занят.
class FunctionalTest(StaticLiveServerTestCase):
"""Functional Testing base class."""
port = 50500

# resulsts in:
# OSError: [Errno 98] Address in use

Другой вариант, о котором я подумал, — это установить URL-адрес Selenium для моего работающего веб-приложения, но тогда тестовая база данных, созданная StaticLiveServerTestCase, не будет использоваться. Вместо этого он использует контейнер postgres, в котором невозможно найти объекты, созданные на этапе установки. В моем примере теста пользователь не может войти в систему, потому что Selenium обращается к версии приложения, обслуживающей базу данных Postgres, а не тестовую базу данных.
self.live_server_url = "http://web:8000"

# results in
# AssertionError: 'Profile' not found in 'Sign In'
# the surrounding code is setup correctly, so this normally results in success.

Настройка
Я пытаюсь создать конвейер для разработки через тестирование. Для этого я выбрал Django в качестве веб-приложения, Postgres в качестве базы данных (разработка и производство) и использую Selenium для своих функциональных тестов. Все это происходит в docker-контейнерах, предоставленных docker compose. Когда я отправляю свой код на свой собственный Gitlab, конвейер создает контейнер и запускает все тесты. Ошибка также возникает на моей машине разработки.
Я тестирую следующим образом:
docker Compose Up -d
Docker Compose Exec Web Python3 Manage.py Test
Я впервые настраиваю что-то подобное, поэтому, возможно, я просто путаю разные понятия.
Код
docker-compose.yml
services:
web:
build: .
develop:
watch:
- action: sync
path: ./src
target: /src
- action: rebuild
path: requirements.txt
ports:
- 8000:8000
environment:
- SECRET_KEY='django-insecure-5&!h2y%p8)l1than6$$jsl$$jb^*7sp+446b7gjfd_fu8=tx_=&9'
- DEBUG=1
- DB_HOST=db
- DB_NAME=devdb
- DB_USER=devuser
- DB_PASS=changeme
- DJANGO_SUPERUSER_PASSWORD=testpass123
- DJANGO_SUPERUSER_USERNAME=admin
- DJANGO_SUPERUSER_EMAIL=admin@mail.com
- ALLOWED_HOSTS=*
depends_on:
db:
condition: service_healthy
command: >
sh -c "python manage.py wait_for_db &&
python manage.py migrate &&
python manage.py createsuperuser --noinput &&
python manage.py runserver 0.0.0.0:8000"
db:
image: postgres:13-alpine
environment:
- POSTGRES_DB=devdb
- POSTGRES_USER=devuser
- POSTGRES_PASSWORD=changeme
ports:
- 5432:5432
healthcheck:
test: ["CMD-SHELL", "pg_isready", "-d", "db_prod"]
interval: 30s
timeout: 60s
retries: 5
start_period: 80s
selenium-chrome:
image: selenium/standalone-chrome:131.0
ports:
- 4444:4444
- 5900:5900
- 7900:7900

test.py
"""Base functional testing class."""

import os
import socket
import uuid
from urllib.parse import urlparse

from django.contrib.auth import get_user_model
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from selenium import webdriver
from selenium.webdriver.common.by import By

class FunctionalTest(StaticLiveServerTestCase):
"""Functional Testing base class."""

def setUp(self):
"""Setup Selenium and test database access."""
super().setUpClass()

host_ip = socket.gethostbyname(socket.gethostname())
host_port = urlparse(self.live_server_url).port

# Selenium cannot access the website because the random port is not open.
self.live_server_url = f"http://{host_ip}:{host_port}"

# # Selenium can access the web site with this
# # but Django does not use the testing database created by testcase
# self.live_server_url = "http://web:8000"

options = webdriver.ChromeOptions()
self.browser = webdriver.Remote(
command_executor="http://selenium-chrome:4444/wd/hub",
options=options
)

def tearDown(self):
"""Shutdown browser."""
self.browser.quit()
super().tearDown()

def create_test_user(self):
"""Creates a test user."""
User = get_user_model()
self.normal_user_credentials = {
"username": f"normal_user{str(uuid.uuid4())}",
"password": "testpass1234",
"email": "normal_user@email.com"
}
self.normal_user = User.objects.create_user(
username=self.normal_user_credentials["username"],
email=self.normal_user_credentials["email"],
password=self.normal_user_credentials["password"]
)
self.normal_user_credentials["id"] = self.normal_user.id

def test_login(self):
"""Login as existing user."""
self.browser.get(f"{self.live_server_url}/accounts/login/")

# Find input fields
username_input = self.browser.find_element(self, By.NAME,"login")
password_input = self.browser.find_element(self, By.NAME,"password")

# Fill out form
username_input.send_keys(self.normal_user_credentials["username"])
password_input.send_keys(self.normal_user_credentials["password"])

# Submit form
self.browser.find_element(self, By.XPATH, "//button[@type='submit']").click()
header_text = self.browser.find_element(self, By.TAG_NAME, "h1").text

# Check if login was successful
self.assertIn("Profile", header_text)


Подробнее здесь: https://stackoverflow.com/questions/792 ... n-docker-o
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»