Skip to content

Commit 1cd2ac5

Browse files
Finished writing Part 4
1 parent fbdbfdf commit 1cd2ac5

File tree

3 files changed

+91
-7
lines changed

3 files changed

+91
-7
lines changed

tests/conftest.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""
2+
This module contains shared fixtures.
3+
"""
4+
5+
import pytest
6+
7+
from pages.result import DuckDuckGoResultPage
8+
from pages.search import DuckDuckGoSearchPage
9+
10+
11+
@pytest.fixture
12+
def result_page(page):
13+
return DuckDuckGoResultPage(page)
14+
15+
16+
@pytest.fixture
17+
def search_page(page):
18+
return DuckDuckGoSearchPage(page)

tests/test_search.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@
22
These tests cover DuckDuckGo searches.
33
"""
44

5-
from pages.result import DuckDuckGoResultPage
6-
from pages.search import DuckDuckGoSearchPage
7-
8-
9-
def test_basic_duckduckgo_search(page):
10-
search_page = DuckDuckGoSearchPage(page)
11-
result_page = DuckDuckGoResultPage(page)
5+
def test_basic_duckduckgo_search(search_page, result_page):
126

137
# Given the DuckDuckGo home page is displayed
148
search_page.load()

workshop/4-page-objects.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,75 @@ Rerun the test again to make sure everything is still working.
323323

324324

325325
## Page object fixtures
326+
327+
There is one more thing we can do to maximize the value of our new page objects:
328+
we can create fixtures to automatically construct them!
329+
In our current test, we construct them explicitly inside the test function.
330+
If we add more test functions in the future, that construction code will become repetitive.
331+
Page object fixtures will help our code stay concise.
332+
333+
In pytest, shared fixtures belong in a module under the `tests` directory named `conftest.py`.
334+
Create `tests/conftest.py` and add the following code:
335+
336+
```python
337+
import pytest
338+
339+
from pages.result import DuckDuckGoResultPage
340+
from pages.search import DuckDuckGoSearchPage
341+
342+
343+
@pytest.fixture
344+
def result_page(page):
345+
return DuckDuckGoResultPage(page)
346+
347+
348+
@pytest.fixture
349+
def search_page(page):
350+
return DuckDuckGoSearchPage(page)
351+
```
352+
353+
The two fixtures, `result_page` and `search_page`,
354+
each call the Playwright `page` fixture and use it to construct a page object.
355+
Just like `page`, they have function scope.
356+
If both page object fixtures are called for the same test
357+
(like we will do for `test_basic_duckduckgo_search`),
358+
then they will both receive the same `page` object due to fixture scope.
359+
You can learn more about fixtures from the
360+
[pytest fixtures](https://docs.pytest.org/en/6.2.x/fixture.html) doc page.
361+
362+
To use these new fixtures, rewrite `tests/test_search.py` like this:
363+
364+
```python
365+
def test_basic_duckduckgo_search(search_page, result_page):
366+
367+
# Given the DuckDuckGo home page is displayed
368+
search_page.load()
369+
370+
# When the user searches for a phrase
371+
search_page.search('panda')
372+
373+
# Then the search result query is the phrase
374+
assert 'panda' == result_page.search_input_value()
375+
376+
# And the search result links pertain to the phrase
377+
assert result_page.result_link_titles_contain_phrase('panda')
378+
379+
# And the search result title contains the phrase
380+
assert 'panda' in result_page.title()
381+
```
382+
383+
Notice a few things:
384+
385+
* This test module no longer needs to import the page object classes from the `pages` module.
386+
* The `search_page` and `result_page` fixtures are declared as arguments for the test function.
387+
* The test function no longer explicitly constructs page objects.
388+
* The Playwright `page` fixture is no longer declared because it is no longer called directly by the test function.
389+
390+
If you use page objects, then **all interactions should be performed using page objects**.
391+
It is not recommended to mix raw Playwright calls with page object calls.
392+
That becomes confusing, and it encourages poor practices like dirty hacks and copypasta.
393+
It also causes a test automation project to lose strength from a lack of conformity in design.
394+
395+
Rerun the test one more time to make sure the fixtures work as expected.
396+
Congratulations!
397+
You have finished refactoring this test case using page objects.

0 commit comments

Comments
 (0)