@@ -323,3 +323,75 @@ Rerun the test again to make sure everything is still working.
323
323
324
324
325
325
## 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