# Testing | NiceGUI

[Button: icon:menu]

[](/)

[Installation](/#installation)

[Features](/#features)

[Demos](/#demos)

[Documentation](/documentation)

[Examples](/examples)

[Why?](/#why)

[Button]

[Button]

[](https://github.com/zauberzeug/nicegui/)

[Button: icon:more_vert]

# *Testing*

## Running Integration Tests


    The NiceGUI package provides a [pytest plugin](https://docs.pytest.org/en/stable/how-to/writing_plugins.html)
    which can be activated via `-p nicegui.testing.plugin` parameter.
    This makes specialized [fixtures](https://docs.pytest.org/en/stable/explanation/fixtures.html)
    available which allows you to write integration tests for your NiceGUI user interface.
    With the [`screen` fixture](/documentation/screen) you can run integration tests through a headless browser (slow).
    On the other hand the [`user` fixture](/documentation/user) allows integration tests to be fully simulated in Python (fast).
    If you only want one kind of test fixtures,
    you can also use the plugin `nicegui.testing.user_plugin` or `nicegui.testing.screen_plugin`.

    There are a multitude of ways to structure your project and tests.
    Here we only present our preferred approach for small and large projects which is on the one hand very easy but yet super powerful.
    For other approaches please check the [pytest documentation](https://docs.pytest.org/en/stable/contents.html).


## Set main file


    You need to tell the pytest plugin which of your files is the main entry point for your NiceGUI application (containing the `ui.run` call).
    This can be done in three ways:

    1. Name your main file `main.py` - if you do nothing else, the test plugin will look for this file and load it.
    2. Set the `main_file` option in the `pytest.ini` configuration file in the root of your project.
    3. Mark your test functions with the `@pytest.mark.nicegui_main_file` decorator (if you maintain multiple apps in the same codebase).

    The main file will automatically be used as an entry point for each integration test (`user` fixture or `screen` fixture).
    You also need to set the [`asyncio_mode = auto`](/documentation/user#async_execution) option
    and the plugin to be used (`nicegui.testing.plugin`, `nicegui.testing.user_plugin` or `nicegui.testing.screen_plugin`)
    in the `pytest.ini` file.

    *Added in version 3.0.0*
    *Updated in version 3.1.0: Added the "nicegui_main_file" marker.*


app.py

[Button]

````python
from nicegui import ui

def root() -> None:
    ui.button('Click me', on_click=lambda: ui.notify('Hello World!'))

ui.run(root)

````

test_app.py

[Button]

````python
from nicegui import ui
from nicegui.testing import User

async def test_click(user: User) -> None:
    await user.open('/')
    await user.should_see('Click me')
    user.find(ui.button).click()
    await user.should_see('Hello World!')

````

pytest.ini

[Button]

````ini
[pytest]
asyncio_mode = auto
main_file = app.py
addopts = -p nicegui.testing.user_plugin

````


    Please also have a look at the examples
    [Chat App](https://github.com/zauberzeug/nicegui/tree/main/examples/chat_app),
    [Todo List](https://github.com/zauberzeug/nicegui/tree/main/examples/todo_list/),
    [Authentication](https://github.com/zauberzeug/nicegui/tree/main/examples/authentication)
    and our [more complex pytest example](https://github.com/zauberzeug/nicegui/tree/main/examples/pytests)
    for demonstration.


## [User Fixture](/documentation/user)


        We recommend utilizing the `user` fixture instead of the [`screen` fixture](/documentation/screen) wherever possible
        because execution is as fast as unit tests and it does not need Selenium as a dependency.
        The `user` fixture cuts away the browser and replaces it by a lightweight simulation.

        You can assert to "see" specific elements or content, click buttons, type into inputs and trigger events.
        We aimed for a nice API to write acceptance tests which read like a story and are easy to understand.
        Due to the fast execution, the classical [test pyramid](https://martinfowler.com/bliki/TestPyramid.html),
        where UI tests are considered to be slow, error prone and expensive, does not apply anymore 🚀.
    

example

[Button]

````python
await user.open('/')
user.find('Username').type('user1')
user.find('Password').type('pass1').trigger('keydown.enter')
await user.should_see('Hello user1!')
user.find('logout').click()
await user.should_see('Log in')

````


        **NOTE:** The `user` fixture might still miss some features.
        Please let us know in separate feature requests
        [over on GitHub](https://github.com/zauberzeug/nicegui/discussions/new?category=ideas-feature-requests).
    

[See more →](/documentation/user)

## [Screen Fixture](/documentation/screen)


        The `screen` fixture starts a real (headless) browser to interact with your application.
        This is only necessary if you have browser-specific behavior to test.
        NiceGUI itself is thoroughly tested with this fixture to ensure each component works as expected.
        Therefore we recommend to only use it if you absolutely have to.
    

example

[Button]

````python
from selenium.webdriver.common.keys import Keys

screen.open('/')
screen.type(Keys.TAB) # to focus on the first input
screen.type('user1')
screen.type(Keys.TAB) # to focus the second input
screen.type('pass1')
screen.click('Log in')
screen.should_contain('Hello user1!')
screen.click('logout')
screen.should_contain('Log in')

````

[See more →](/documentation/screen)

**Nice**GUI

The Python UI framework that shows up in your browser.

[](https://github.com/zauberzeug/nicegui/)

[](https://discord.gg/TEpFeAaF4f)

[](https://www.reddit.com/r/nicegui/)

Resources

[Documentation](/documentation)

[Examples](/examples)

[LLM reference](/llms.txt)

[GitHub](https://github.com/zauberzeug/nicegui/)

[PyPI](https://pypi.org/project/nicegui/)

Community

[Discussions](https://github.com/zauberzeug/nicegui/discussions)

[Discord](https://discord.gg/TEpFeAaF4f)

[Reddit](https://www.reddit.com/r/nicegui/)

[Contributing](https://github.com/zauberzeug/nicegui/blob/main/CONTRIBUTING.md)

[Sponsors](https://github.com/sponsors/zauberzeug)

Legal

[Imprint](/imprint_privacy#imprint)

[Privacy](/imprint_privacy#privacy)

Made with NiceGUI by [Zauberzeug](https://zauberzeug.com)

© 2026 [Zauberzeug GmbH](https://zauberzeug.com)