首页 > 解决方案 > Selenium 登录测试不接受 pytest 固定装置进行登录或拒绝连接

问题描述

我越来越绝望,因为我似乎无法为我认为所有人都会使用的东西找到解决方案。

我想用 selenium 和 pytest 用 live_server url 测试一个简单的登录。根据 pytest-django doc,一个名为的简单夹具live_server应该可以解决问题(https://pytest-django.readthedocs.io/en/latest/helpers.html#live-server)。

不幸的是,当我将此夹具传递给我的测试并尝试使用它访问我的网站时,我得到:

本地主机拒绝连接

例如:

    def test_selenium(self, live_server, create_staff_user_in_db):
        browser = webdriver.Remote(
            command_executor='http://selenium:4444/wd/hub',
            desired_capabilities=DesiredCapabilities.CHROME,
        )

        browser.get(live_server.url)

利用这个问题Selenium 无法登录到 Django LiveServerTestCase我正在尝试使用不同的服务器装置,然后连接我,我可以在我的 VNC 查看器中看到我的网站。

@pytest.fixture
def test_server() -> LiveServer:
    addr = socket.gethostbyname(socket.gethostname())
    server = LiveServer(addr)
    yield server
    server.stop()

但是有了这个,如果我用我的装置在数据库中创建用户,我现在无法登录到我的网站。尽管看起来用户实际上是被创建的。所以我的测试现在看起来像:


  def test_selenium(self, test_server, create_staff_user_in_db):
        browser = webdriver.Remote(
            command_executor='http://selenium:4444/wd/hub',
            desired_capabilities=DesiredCapabilities.CHROME,
        )

        browser.get(f"{live_server.url}/login")
        input_username = browser.find_element_by_name('username')
        input_password = browser.find_element_by_name('password')
        input_username.send_keys('testuserstaff')
        input_password.send_keys('mypasswordstaff')
        browser.find_element_by_xpath(
            '//*[@id="page-top"]/div[1]/div/div/div/div/form/button'
        ).click()

我的用户装置是:

@pytest.fixture()
def create_staff_user_in_db():
    User = get_user_model()
    staff_user = User.objects.create_user(
        username="testuserstaff",
        password="mypasswordstaff",
    )
    staff_user.is_staff = True
    staff_user.save()

    return staff_user

测试访问我的登录页面但无法登录。我 100% 确定我使用了正确的凭据。

如果我打印出来进行调试,我还可以验证我的用户是否在我的数据库中:

print(u.username) ==> testuserstaff
print(u.password) ==> igetthehashofthepassword
print(User.objects.count()) ==> 1 

因此,我假设由 pytest 创建的数据库填充了我作为夹具传递的这个用户。现在不知何故,我的实时服务器要么不使用数据库,要么不识别灯具。

它必须连接到 live_server/test_server 固定装置。如果有任何帮助,我将不胜感激。我觉得我很接近,但我似乎无法找出它为什么不登录。

我还尝试了什么:1)使用我的开发数据库中的用户登录。没有成功。所以我想知道:然后使用什么数据库?

2)我尝试设置 pytest-selenium 库。如果我尝试加载一个页面,我会得到selenium.common.exceptions.SessionNotCreatedException: Message: Unable to create session

3) 我尝试使用 StaticLiveServerCase,但这不是一个选项,因为我需要将固定装置作为参数传递。

4)我在网上到处搜索,找不到其他任何东西

也很高兴知道:

我在 docker 环境中运行它(如果有帮助,很高兴分享)

所以我的堆栈基本上是:Docker、Django、Pytest、selenium

再次,真的很感激在这里。非常感谢提前

编辑:

我的码头工人撰写文件:

version: '3'

volumes:
  local_postgres_data: {}
  local_postgres_data_backups: {}

services:
  django:
    build:
      context: .
      dockerfile: ./compose/local/django/Dockerfile
    image: mywebsite_local_django
    depends_on:
      - postgres
    volumes:
      - .:/app
    env_file:
      - ./.envs/.local/.django
      - ./.envs/.local/.postgres
    ports:
      - "8000:8000"
    command: /start

  selenium:
    image: selenium/standalone-chrome-debug
    ports:
      - 4444:4444
      - 5900:5900

  postgres:
    build:
      context: .
      dockerfile: ./compose/production/postgres/Dockerfile
    image: mywebsite_production_postgres
    volumes:
      - local_postgres_data:/var/lib/postgresql/data
      - local_postgres_data_backups:/backups
    env_file:
      - ./.envs/.local/.postgres

标签: pythondockerseleniumpytest

解决方案


将评论变成答案:默认情况下,测试避免运行 db 查询以不减慢测试运行速度,因此User.objects.create_user不写入数据库。为了确保 db 提交,请@pytest.mark.django_db(transaction=True)在测试中使用标记或transactional_db在您的固定装置中使用固定装置:

@pytest.fixture()
def create_staff_user_in_db(transactional_db):
    staff_user = User.objects.create_user(...)
    ...

我假设live_serverdjango 的夹具会transactional_db自动使用,但test_server不是吗?

完全正确 -live_server暗示事务模式,但自定义 impltest_server没有。明确请求transactional_db固定装置test_server应该修复它:

@pytest.fixture
def test_server(request) -> LiveServer:
    request.getfixturevalue("transactional_db")
    ...

顺便说一句,如果您只想动态应用实时服务器地址,则不需要定义自己的夹具;编写配置值就足够了。例子:

# conftest.py

def pytest_configure(config):
    config.option.liveserver = socket.gethostbyname(socket.gethostname())

然后,该值将由内置live_server夹具使用。将其conftest.py放入您的项目或测试根目录,以便pytest尽早找到 hookimpl 以便应用它。


推荐阅读