问题
I'm getting desperate because I can't seem to find a solution for what I thought would be used by everyone out there.
I want to test a simple login with selenium and pytest with a live_server url. According to pytest-django doc, a simple fixture called live_server should do the trick (https://pytest-django.readthedocs.io/en/latest/helpers.html#live-server).
Unfortunately when I pass this fixture to my test and try to visit my website with it I get:
localhost refused to connect
for example for this:
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)
Leveraging this question Selenium unable to login to Django LiveServerTestCase I am trying to use a different server-fixture which then connects me and I can see my website in my VNC viewer.
@pytest.fixture
def test_server() -> LiveServer:
addr = socket.gethostbyname(socket.gethostname())
server = LiveServer(addr)
yield server
server.stop()
But with this I am now not able to login to my website if I create users in the db with my fixtures. Even though it seems like users are actually created. So my test now looks like:
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()
And my user fixture is:
@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
The tests visits my login page and fails to log in. I am 100% certain that I am using the right credentials.
If I print out for debugging I also can verify that my user is in my db:
print(u.username) ==> testuserstaff
print(u.password) ==> igetthehashofthepassword
print(User.objects.count()) ==> 1
Thus I assume the db that is being created by pytest is filled with this user I pass as fixture. Now somehow my live server is either not using the db or not recognising the fixtures.
It must be connected to the live_server/test_server fixture. I would be supergrateful for any help. I feel like I am so close but I just can't seem to find out why it doesn't log in.
What else have I tried: 1) Login in with users that are in my development db. No success. So I am wondering: What db is then be used?
2) I tried to setup pytest-selenium library. If I try to load a page I get selenium.common.exceptions.SessionNotCreatedException: Message: Unable to create session
3) I tried to work with StaticLiveServerCase, but this is not an option since I need to pass fixtures as an argument.
4) I searched everywhere on the web and cannot find anything else
Also good to know:
I am running this in a docker environment (happy to share if it helps)
So my stack is basically: Docker, Django, Pytest, selenium
Again, would really appreciate a hand here. Thanks so much in advance
EDIT:
My docker-compose file:
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
回答1:
Turning the comment into an answer: by default, the tests avoid running db queries to not to slow down the test run, so User.objects.create_user doesn't write to database. To ensure db commits, use the @pytest.mark.django_db(transaction=True) marker in tests or the transactional_db fixture in your fixtures:
@pytest.fixture()
def create_staff_user_in_db(transactional_db):
staff_user = User.objects.create_user(...)
...
I assume that the
live_serverfixture of django usestransactional_dbautomatically but that thetest_serverdoesn't?
Exactly - live_server implies the transactional mode, but the custom impl of test_server doesn't. Explicitly requesting the transactional_db fixture in test_server should fix it:
@pytest.fixture
def test_server(request) -> LiveServer:
request.getfixturevalue("transactional_db")
...
BTW if you just want to apply the live server address dynamically, you shouldn't need to define your own fixture; writing config values should suffice. Example:
# conftest.py
def pytest_configure(config):
config.option.liveserver = socket.gethostbyname(socket.gethostname())
This value will then be used by the builtin live_server fixture. Put the conftest.py into your project or tests root dir to make pytest find the hookimpl early enough for it to be applied.
来源:https://stackoverflow.com/questions/60744437/selenium-login-test-doesnt-accept-pytest-fixtures-for-login-or-refuses-to-conne