Selenium 登录测试不接受用于登录的 pytest 固定装置或拒绝连接

Mic*_*gas 6 python selenium pytest docker

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

我想用 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)
Run Code Online (Sandbox Code Playgroud)

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

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

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


  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()

Run Code Online (Sandbox Code Playgroud)

我的用户夹具是:

@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
Run Code Online (Sandbox Code Playgroud)

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

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

print(u.username) ==> testuserstaff
print(u.password) ==> igetthehashofthepassword
print(User.objects.count()) ==> 1 
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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

也很高兴知道:

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

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

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

编辑:

我的 docker-compose 文件:

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
Run Code Online (Sandbox Code Playgroud)

hoe*_*ing 2

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

@pytest.fixture()
def create_staff_user_in_db(transactional_db):
    staff_user = User.objects.create_user(...)
    ...
Run Code Online (Sandbox Code Playgroud)

我假设live_serverdjango 的固定装置会transactional_db自动使用,但不会test_server吗?

确切地说 -live_server意味着事务模式,但 的自定义实现则test_server不然。明确请求transactional_db固定装置test_server应该修复它:

@pytest.fixture
def test_server(request) -> LiveServer:
    request.getfixturevalue("transactional_db")
    ...
Run Code Online (Sandbox Code Playgroud)

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

# conftest.py

def pytest_configure(config):
    config.option.liveserver = socket.gethostbyname(socket.gethostname())
Run Code Online (Sandbox Code Playgroud)

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