Welcome to pytest-pyppeteer’s documentation!¶
pytest-pyppeteer is a plugin to run pyppeteer in pytest.
Documents¶
Quickstart¶
For example, query the rating of the movie The Shawshank Redemption on douban.com.
from dataclasses import dataclass
@dataclass(init=False)
class Elements:
url = "https://movie.douban.com/"
query = "#inp-query"
apply = ".inp-btn > input:nth-child(1)"
result = (
"#root > div > div > div > div > div:nth-child(1) > div.item-root a.cover-link"
)
rating = (
"#interest_sectl > div.rating_wrap.clearbox > div.rating_self.clearfix > strong"
)
async def test_pyppteer(pyppeteer):
page = await pyppeteer.new_page()
await page.goto(Elements.url)
await page.type(Elements.query, "The Shawshank Redemption")
await page.click(Elements.apply)
await page.waitfor(Elements.result)
await page.click(Elements.result)
await page.waitfor(Elements.rating)
rating = await page.get_value(Elements.rating)
assert rating == 0
The test will be failed because of assert rating == 0
, but we successfully got the rating of the movie, it was 9.7
.
$ pipenv run pytest -q tests/test_quickstart.py
F [100%]
====================================== FAILURES ======================================
_________________________________ test_options_mark __________________________________
pyppeteer = Browser(pyppeteer_browser=<pyppeteer.browser.Browser object at 0x10917e5e0>)
async def test_options_mark(pyppeteer):
page = await pyppeteer.new_page()
await page.goto("https://movie.douban.com")
await page.type(Elements.query, "The Shawshank Redemption")
await page.click(Elements.apply)
await page.waitfor(Elements.result)
await page.click(Elements.result)
await page.waitfor(Elements.rating)
rating = await page.get_value(Elements.rating)
> assert rating == 0
E AssertionError: assert '9.7' == 0
tests/test_quickstart.py:31: AssertionError
================================== warnings summary ==================================
tests/test_quickstart.py::test_options_mark
tests/test_quickstart.py::test_options_mark
tests/test_quickstart.py::test_options_mark
tests/test_quickstart.py::test_options_mark
tests/test_quickstart.py::test_options_mark
tests/test_quickstart.py::test_options_mark
tests/test_quickstart.py::test_options_mark
/Users/yaomeng/.local/share/virtualenvs/pytest-pyppeteer-KPzLwmKN/lib/python3.8/site-packages/pyee/_compat.py:35: DeprecationWarning: pyee.EventEmitter is deprecated and will be removed in a future major version; you should instead use either pyee.AsyncIOEventEmitter, pyee.TwistedEventEmitter, pyee.ExecutorEventEmitter, pyee.TrioEventEmitter, or pyee.BaseEventEmitter.
warn(DeprecationWarning(
-- Docs: https://docs.pytest.org/en/stable/warnings.html
============================== short test summary info ===============================
FAILED tests/test_quickstart.py::test_options_mark - AssertionError: assert '9.7' == 0
1 failed, 7 warnings in 7.61s

Usage¶
Command line options¶
--executable-path
¶
You can specify the path to a Chromium or Chrome executable. otherwise
pytest-pyppeteer will use the default installation location of Chrome
in current platform, but now only support win64
, win32
and
mac
platform.
For other platforms, pyppeteer will downloads the recent version of Chromium when called first time. If you don’t prefer this behavior, you can specify an exact path by override this fixture:
@pytest.fixture(scope="session")
def executable_path(executable_path):
if executable_path is None:
return "path/to/Chrome/or/Chromium"
return executable_path
Note
The default installation location of Chrome in different platform:
win64
: C:/Program Files/Google/Chrome/Application/chrome.exewin32
: C:/Program Files (x86)/Google/Chrome/Application/chrome.exemac
: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
--headless
¶
Run browser in headless mode.
--args
¶
Additional args to pass to the browser instance.
For example, specify a proxy:
$ pytest --args proxy-server "localhost:5555,direct://" --args proxy-bypass-list "192.0.0.1/8;10.0.0.1/8"
Or by override the args
fixture:
@pytest.fixture(scope="session")
def args(args) -> List[str]:
return args + [
"--proxy-server=localhost:5555,direct://",
"--proxy-bypass-list=192.0.0.1/8;10.0.0.1/8",
]
--window-size
¶
The default browser size is 800*600, you can use this option to change this behavior:
$ pytest --window-size 1200 800
--window-size 0 0
means to starts the browser maximized.
--slow
¶
Slow down the pyppeteer operate in milliseconds. Defaults to 0.0
.
No matter selector or xpath¶
pyppeteer
fixture provide a pytest_pyppeteer.models.Browser
instance, its
usage is almost the same as pyppeteer.browser.Browser
, except that it provides
a new instance method: new_page()
, which is similar to newPage()
, but it
returns a pytest_pyppeteer.models.Page
instead of pyppeteer.page.Page
.
pytest_pyppeteer.models.Page
’s usage is also the same as pyppeteer.page.Page
,
but it provides some new instance methods, and override some methods. For example,
you can query an element by selector or xpath in just same method query_locator
instead of original querySelector
and xpath
.
You can also get an original Page
by pyppeteer.newPage()
.
options
marker¶
You can override some command line options in the specified test.
For example, auto-open a DevTools panel:
import asyncio
import pytest
@pytest.mark.options(devtools=True)
async def test_marker(pyppeteer):
await pyppeteer.new_page()
await asyncio.sleep(2)

Advanced Usage¶
Control multiple browsers asynchronously¶
You can easily to control multiple browsers at the same time.
For example, query the The Shawshank Redemption’s movie and book rating on douban.com at the same time, then compare them.
import asyncio
from dataclasses import dataclass
from typing import TYPE_CHECKING, Callable
import pytest
if TYPE_CHECKING:
from .models import Browser, Page
@dataclass
class Elements:
query = "#inp-query"
apply = ".inp-btn > input:nth-child(1)"
@dataclass
class BookElements(Elements):
url = "https://book.douban.com/"
result = '(//*[@class="item-root"])[1]/a'
rating = "#interest_sectl > div > div.rating_self.clearfix > strong"
@dataclass
class MovieElements(Elements):
url = "https://movie.douban.com/"
result = (
"#root > div > div > div > div > div:nth-child(1) > div.item-root a.cover-link"
)
rating = (
"#interest_sectl > div.rating_wrap.clearbox > div.rating_self.clearfix > strong"
)
async def query_rating(pyppeteer: "Browser", name: str, elements: "Elements"):
page: Page = await pyppeteer.new_page()
await page.goto(elements.url)
await page.type(elements.query, name)
await page.click(elements.apply)
await page.waitfor(elements.result)
await page.click(elements.result)
await page.waitfor(elements.rating)
rating = await page.get_value(elements.rating)
return rating
async def test_multiple_browsers(pyppeteer_factory: "Callable"):
pyppeteer1 = await pyppeteer_factory()
pyppeteer2 = await pyppeteer_factory()
movie_rating, book_rating = await asyncio.gather(
query_rating(pyppeteer1, "The Shawshank Redemption", MovieElements),
query_rating(pyppeteer2, "The Shawshank Redemption", BookElements),
)
assert movie_rating == book_rating
Execute this test, and it will be failed:
$ pipenv run pytest -q tests/test_multiple_browsers.py
F [100%]
====================================== FAILURES ======================================
_______________________________ test_multiple_browsers _______________________________
pyppeteer_factory = <function pyppeteer_factory.<locals>._factory at 0x1068c4700>
async def test_multiple_browsers(pyppeteer_factory: "Callable"):
pyppeteer1 = await pyppeteer_factory()
pyppeteer2 = await pyppeteer_factory()
movie_rating, book_rating = await asyncio.gather(
query_rating(pyppeteer1, "The Shawshank Redemption", MovieElements),
query_rating(pyppeteer2, "The Shawshank Redemption", BookElements),
)
> assert movie_rating == book_rating
E AssertionError: assert '9.7' == '9.2'
E - 9.2
E + 9.7
tests/test_multiple_browsers.py:62: AssertionError
================================== warnings summary ==================================
tests/test_multiple_browsers.py: 14 warnings
/Users/yaomeng/.local/share/virtualenvs/pytest-pyppeteer-KPzLwmKN/lib/python3.8/site-packages/pyee/_compat.py:35: DeprecationWarning: pyee.EventEmitter is deprecated and will be removed in a future major version; you should instead use either pyee.AsyncIOEventEmitter, pyee.TwistedEventEmitter, pyee.ExecutorEventEmitter, pyee.TrioEventEmitter, or pyee.BaseEventEmitter.
warn(DeprecationWarning(
-- Docs: https://docs.pytest.org/en/stable/warnings.html
============================== short test summary info ===============================
FAILED tests/test_multiple_browsers.py::test_multiple_browsers - AssertionError: as...
1 failed, 14 warnings in 17.58s

API Reference¶
errors module¶
-
class
ErrorMixin
(**ctx: Any)[source]¶ Bases:
object
The mixin for base exceptions.
- Parameters
ctx (Any) – content variables.
-
exception
Error
(**ctx: Any)[source]¶ Bases:
errors.ErrorMixin
,Exception
Base-class for all exceptions raised by this plugin.
-
exception
PathError
(path: str, **kwargs: Any)[source]¶ Bases:
errors.Error
The base-class for all path-related exceptions.
- Parameters
path (str) – path string.
-
exception
PathNotAExecutableError
(path: str, **kwargs: Any)[source]¶ Bases:
errors.PathError
-
exception
LocatorError
(locator: str, **kwargs: Any)[source]¶ Bases:
errors.Error
The base-class for all locator-related exceptions.
- Parameters
path (str) – locatore string.
-
exception
LocatorNotAValidSelectorOrXPathError
(locator: str, **kwargs: Any)[source]¶ Bases:
errors.LocatorError
-
exception
ElementError
(locator: str, **kwargs: Any)[source]¶ Bases:
errors.Error
The base-class for all element-related exceptions.
- Parameters
locator (str) – element locator string.
-
exception
ElementNotExistError
(locator: str, **kwargs: Any)[source]¶ Bases:
errors.ElementError
hooks module¶
models module¶
-
class
ViewPort
(*, width: int = 800, height: int = 600, deviceScaleFactor: float = 1.0, isMobile: bool = False, hasTouch: bool = False, isLandscape: bool = False)[source]¶ Bases:
pydantic.main.BaseModel
Keep the consistency of each page’s viewport in a browser instance.
One of the most important use is as the standard setting model for
Options.defaultViewport
.
-
class
Options
(*, args: List[str] = [], autoClose: bool = True, defaultViewport: models.ViewPort = ViewPort(width=800, height=600, deviceScaleFactor=1.0, isMobile=False, hasTouch=False, isLandscape=False), devtools: bool = False, dumpio: bool = False, env: dict = None, executablePath: Union[str, Path] = None, handleSIGINT: bool = True, handleSIGTERM: bool = True, handleSIGHUP: bool = True, headless: bool = False, ignoreHTTPSErrors: bool = True, ignoreDefaultArgs: Union[bool, List[str]] = False, logLevel: Optional[Union[int, str]] = None, slowMo: float = 0.0, userDataDir: str = None)[source]¶ Bases:
pydantic.main.BaseModel
The standard setting model for pyppeteer launcher.
-
args
: List[str]¶ Additional arguments to pass to the browser instance. The list of Chromium flags can be found here. Defaults to
list()
.
-
defaultViewport
: Optional[ViewPort]¶ Set a consistent viewport for each page. Defaults to a default
ViewPort
instance.None
means disables the default viewport.
-
devtools
: bool¶ Whether to auto-open a DevTools panel for each tab. If this option is
True
, theheadless
option will be setFalse
. Defaults toFalse
.
-
dumpio
: bool¶ Whether to pipe the browser process stdout and stderr into
process.stdout
andprocess.stderr
. Defaults toFalse
.
-
env
: Optional[dict]¶ Specify environment variables that will be visible to the browser.
None
means that same as python process. Defaults toNone
.
-
executablePath
: Union[str, Path]¶ Path to a Chromium or Chrome executable.
None
means use the default bundled Chromium. Defaults toNone
.
-
ignoreDefaultArgs
: Union[bool, List[str]]¶ If
True
, then do not use pyppeteer’s default args. If a list is given, then filter out the given default args. Dangerous option; use with care. Defaults toFalse
.
-
logLevel
: Optional[Union[int, str]]¶ Log level to print logs.
None
means that same as the root logger. Defaults toNone
.
-
slowMo
: float¶ Slow down operations by the specified amount of milliseconds. useful so that you can see what is going on. Defaults to
0.0
.
-
userDataDir
: Optional[str]¶ Path to a User Data Directory. Defaults to
None
.
-
-
class
Browser
(*, pyppeteer_browser: pyppeteer.browser.Browser)[source]¶ Bases:
pydantic.main.BaseModel
-
pyppeteer_browser
: pyppeteer.browser.Browser¶ a pyppeteer browser object.
-
class
Config
[source]¶ Bases:
object
Control the behaviours of pydantic model.
-
arbitrary_types_allowed
= True¶ whether to allow arbitrary user types for fields (they are validated simply by checking if the value is an instance of the type). If False, RuntimeError will be raised on model declaration.
-
-
async
new_page
() → models.Page[source]¶ Make new page on this browser and return its object.
- Returns
a
Page
object.
-
-
class
Page
(*, pyppeteer_page: pyppeteer.page.Page)[source]¶ Bases:
pydantic.main.BaseModel
-
pyppeteer_page
: pyppeteer.page.Page¶ a pyppeteer page object.
-
class
Config
[source]¶ Bases:
object
Control the behaviours of pydantic model.
-
arbitrary_types_allowed
= True¶ whether to allow arbitrary user types for fields (they are validated simply by checking if the value is an instance of the type). If False, RuntimeError will be raised on model declaration.
-
-
async
query_locator
(locator: str) → Optional[ElementHandle][source]¶ Get the element which match
locator
.If no element matches the
locator
, returnNone
.- Parameters
locator (str) – a selector or xpath string
- Returns
an element handle or
None
.
-
async
waitfor
(locator: str, visible: bool = True, hidden: bool = False, timeout: int = 30000) → None[source]¶ Wait until element which matches
locator
.- Parameters
locator (str) – a selector or xpath string.
visible (bool) – Wait for element to be present in DOM and to be visible; i.e. to not have
display: none
orvisibility: hidden
CSS properties. Defaults toTrue
.hidden (bool) – Wait for element to not be found in the DOM or to be hidden, i.e. have
display: none
orvisibility: hidden
CSS properties. Defaults toFalse
.timeout (int) – Maximum time to wait for in milliseconds. Defaults to 30000 (30 seconds). Pass
0
to disable timeout.
- Returns
None
- Raises
ElementTimeoutError – Timeout exceeded while wait for
locator
.
-
async
type
(locator: str, text: str, delay: int = 0, clear: bool = False)[source]¶ Focus the element which matches
locator
and then type text.
-
plugin module¶
-
pytest_addhooks
(pluginmanager: PytestPluginManager) → None[source]¶ Add new hooks.
- Parameters
pluginmanager (_pytest.config.PytestPluginManager) –
- Returns
None
-
pytest_configure
(config: Config) → None[source]¶ Perform initial configuration as follows:
Add
pytest.mark.option
marker to the ini-file option.
- Parameters
config (_pyest.config.Config) – pytest config object.
- Returns
None
Note
This is a
pytest hook function
which is called for every plugin and initial conftest file after command line options have been parsed. After that, the hook is called for other conftest files as they are imported.
-
pytest_collection_modifyitems
(items: List[Item]) → None[source]¶ Modify the items collected by pytest as follows:
Because all test items using pyppeteer should be an asyncio coroutine, here the pytest.mark.asyncio marker is automatically added to each test item collected by pytest.
- Parameters
items (List[pytest.Item]) – the list of items objects collected by pytest.
- Returns
None
Note
This is a
pytest hook function
which is called after collection of all test items is completed.
-
add_asyncio_marker
(item: Item) → Item[source]¶ Add pytest.mark.asyncio marker to the specified item.
If the marker is already exists, return the item directly.
- Parameters
item (pytest.Item) – the pytest item object.
- Returns
the marked item object.
-
is_coroutine
(obj: Any) → bool[source]¶ Check to see if an object is really an asyncio coroutine.
- Parameters
obj (Any) – any object.
- Returns
True or False.
-
pytest_runtest_makereport
(item: Item) → None[source]¶ Implement this pytest hook in wrapper mode, the added behaviors as follows:
Register a new
hooks.pytest_pyppeteer_runtest_makereport_call_debug()
hook which called when a actual failing test calls not setup/teardown.
- Parameters
item (pytest.Item) – the pytest item object.
- Returns
None
-
pytest_addoption
(parser: Parser) → None[source]¶ Register new command line arguments and ini-file values.
Create a new command line option group named pyppeteer, and add the following new options in it:
--executable-path
: path to a Chromium or Chrome executable.--headless
: run browser in headless mode.--args
: additional args to pass to the browser instance. more details refer toargs()
fixture.--window-size
: set the initial browser window size. Defaults to 800 * 600.--window-size 0 0
means to starts the browser maximized.
- Parameters
parser (_pytest.config.argparsing.Parser) – parser for command line arguments and ini-file values.
- Returns
None
Note
This is a
pytest hook function
which be called once at the beginning of a test run to register argparse-style options and ini-style config values.There are two ways to register new options, respectively:
To register a command line option, call
parser.addoption(...)
.To register an ini-file option, call
parser.addini(...)
.
And the options can later be accessed through the
Config
object, respectively:To retrieve the value of a command line option, call
config.getoption(name)
.To retrieve a value read from an ini-style file, call
config.getini(name)
.
The
Config
object is passed around on many pytest internal objects via the.config
attribute or can be retrieved as thepytestconfig
fixture.
-
executable_path
(pytestconfig: Config) → Optional[str][source]¶ Session-scoped fixture
that return Chrome or Chromium executable path.The fixture behaviors follow this procedure:
Return the value passed in from command line option of –executable-path, if it’s not
None
.Return the default installation location of Chrome in current platform, but now only support
win64
,win32
andmac
platform.For other platforms, pyppeteer will downloads the recent version of Chromium when called first time. If you don’t prefer this behavior, you can specify an exact path by overwrite this fixture:
Example:
@pytest.fixture(scope="session") def executable_path(executable_path): if executable_path is None: return "path/to/Chrome/or/Chromium" return executable_path
- Parameters
pytestconfig (_pytest.config.Config) – a session-scoped fixture that return config object.
- Returns
return Chrome or Chromium executable path string. but if current platform isn’t supported, return
None
.
-
args
(pytestconfig: Config) → List[str][source]¶ Session-scoped fixture
that return a list of additional args in the List of Chromium Command Line Arguments to pass to the browser instance.You can use it by command-line option:
Example:
$ pytest --args proxy-server "localhost:5555,direct://" --args proxy-bypass-list "192.0.0.1/8;10.0.0.1/8"
Or overwrite it in your test:
Example:
@pytest.fixture(scope="session") def args(args) -> List[str]: return args + [ "--proxy-server=localhost:5555,direct://", "--proxy-bypass-list=192.0.0.1/8;10.0.0.1/8", ]
- Parameters
pytestconfig (_pytest.config.Config) – a session-scoped fixture that return config object.
- Returns
a list of arguments string. return
list()
if no--args
passed in the command-line.
-
session_options
(pytestconfig: Config, args: List[str], executable_path: str) → Options[source]¶ Session-scoped fixture
that return amodels.Options
object used to initialize browser.- Parameters
pytestconfig (_pytest.config.Config) – a session-scoped fixture that return config object.
args (List[str]) – a session-scoped fixture that return a list of additional args to pass to the browser instance.
executable_path (str) – a session-scoped fixture that return Chrome or Chromium executable path.
- Returns
a
models.Options
object used to initialize browser.
-
options
(request: FixtureRequest, session_options: Options) → Options[source]¶ Function-scoped fixture
that return amodels.Options
object used to initialize browser.This fixture contains all of
session_options()
, plus any options specified by the options markers. Any change to these options will apply only to the tests covered by scope of the fixture override.Example:
@pytest.mark.options(devtools=True) async def test_options_mark(pyppeteer): ...
- Parameters
request (_pytest.fixture.FixtureRequest) – A request object gives access to the requesting test context.
session_options (Options) – a
models.Options
object fromsession_options()
.
- Returns
a
models.Options
object used to initialize browser.
-
get_options_from_markers
(item: Item) → dict[source]¶ Get the options from the
options
markers of test item. And there are only apply on the current test item.- Parameters
item (Item) – the test item object.
- Returns
an dict contains options.
-
pyppeteer_factory
(options: pytest_pyppeteer.models.Options) → Callable[source]¶ Function-scoped fixture
that return a pyppeteer browser factory.- Parameters
options (Options) – a
models.Options
object used to initialize browser- Yield
a pyppeteer browser factory.