Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .markdownlint-cli2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ config:
MD033:
allowed_elements:
- a
- article
- code
- div
- h1
- h2
- img
- li
- p
Expand Down
7 changes: 0 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
<p align="center">
<a href="https://tryke.dev">
<img height="170" alt="tryke-small" src="https://github.com/user-attachments/assets/39a2521a-fe9a-4235-8bb8-97b9e4f68aa7" />
</a>
</p>
<h1 align="center">Tryke</h1>

<p align="center"><a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="ruff" /></a> <a href="https://pypi.org/project/tryke/"><img src="https://img.shields.io/pypi/v/tryke" alt="PyPI" /></a> <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="license" /></a> <a href="https://python.org"><img src="https://img.shields.io/badge/python-3.12%20%7C%203.13%20%7C%203.14%20%7C%203.15-blue.svg" alt="python" /></a> <a href="https://github.com/thejchap/tryke/actions/workflows/release.yml"><img src="https://github.com/thejchap/tryke/actions/workflows/release.yml/badge.svg" alt="CI" /></a> <a href="https://tryke.dev/"><img src="https://img.shields.io/badge/docs-tryke.dev-blue" alt="docs" /></a></p>

<video src="https://github.com/user-attachments/assets/354e21a4-b49f-4e93-a052-df98c0dfc3ae" controls muted></video>

## Highlights

- [Fast](https://tryke.dev/concepts/discovery.html) Rust-powered test discovery
Expand Down
Binary file removed docs/assets/logo.png
Binary file not shown.
172 changes: 86 additions & 86 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Tryke

A Rust-based Python test runner with a Jest-style API.
---
template: home.html
title: Home
description: A Rust-based Python test runner with a Jest-style API.
hide:
- navigation
- toc
---

<p class="md-badges">
<a href="https://github.com/astral-sh/ruff">
Expand All @@ -23,99 +28,94 @@ A Rust-based Python test runner with a Jest-style API.
</a>
</p>

<video src="https://github.com/user-attachments/assets/354e21a4-b49f-4e93-a052-df98c0dfc3ae" controls muted style="max-width: 100%; max-height: 640px;"></video>

## Highlights

<ul class="md-highlights">
<li><span class="hl-icon hl-icon-fast"></span><a href="concepts/discovery.html">Fast</a> Rust-powered test discovery</li>
<li><span class="hl-icon hl-icon-concurrent"></span>Concurrent tests by default</li>
<li><span class="hl-icon hl-icon-pretty"></span>Pretty, per-assertion diagnostics</li>
<li><span class="hl-icon hl-icon-soft"></span><a href="concepts/soft-assertions.html">Soft assertions</a> (like <a href="https://github.com/okken/pytest-check">pytest-check</a>)</li>
<li><span class="hl-icon hl-icon-async"></span>Native <code>async</code> support — no plugin</li>
<li><span class="hl-icon hl-icon-watch"></span><a href="guides/watch-mode.html">Watch mode</a></li>
<li><span class="hl-icon hl-icon-changed"></span><a href="guides/changed-mode.html">Changed mode</a> (like <a href="https://github.com/anapaulagomes/pytest-picked">pytest-picked</a>)</li>
<li><span class="hl-icon hl-icon-clientsrv"></span><a href="concepts/client-server.html">Client/server</a> mode for fast editor integrations</li>
<li><span class="hl-icon hl-icon-fixtures"></span><a href="guides/writing-tests.html#fixtures">Fixtures</a> with setup / teardown and typed <code>Depends()</code> injection</li>
<li><span class="hl-icon hl-icon-cases"></span><a href="concepts/cases.html">Parametrized tests</a> via <code>@test.cases</code></li>
<li><span class="hl-icon hl-icon-describe"></span><a href="guides/writing-tests.html#grouping-tests-with-describe">Grouping</a> with <code>describe()</code> blocks</li>
<li><span class="hl-icon hl-icon-marks"></span><code>skip</code>, <code>skip_if</code>, <code>xfail</code>, and <code>todo</code> markers</li>
<li><span class="hl-icon hl-icon-insource"></span><a href="guides/writing-tests.html#in-source-testing">In-source testing</a></li>
<li><span class="hl-icon hl-icon-doctests"></span>Support for <a href="https://docs.python.org/3/library/doctest.html">doctests</a></li>
<li><span class="hl-icon hl-icon-filter"></span>Filtering and marks</li>
<li><span class="hl-icon hl-icon-reporters"></span><a href="guides/reporters.html">Reporters</a> — text, dot, json, junit, llm, <a href="https://nexte.st">nextest</a>-style, and <a href="https://github.com/Teemu/pytest-sugar">pytest-sugar</a>-style</li>
</ul>

## Getting started

Run tryke with [uvx](https://docs.astral.sh/uv/guides/tools/) to get started quickly:
<div class="tryke-feature-grid">
<article class="tryke-feature-card">
<h2><span class="hl-icon hl-icon-fast"></span>Fast discovery</h2>
<p>Let Rust find your Python tests quickly, with cached discovery built for tight feedback loops.</p>
<a href="concepts/discovery.html">How discovery works <span aria-hidden="true">→</span></a>
</article>

<article class="tryke-feature-card">
<h2><span class="hl-icon hl-icon-concurrent"></span>Concurrent by default</h2>
<p>Run independent tests in parallel without opting into a separate plugin or changing your suite.</p>
<a href="concepts/concurrency.html">Concurrency model <span aria-hidden="true">→</span></a>
</article>

<article class="tryke-feature-card">
<h2><span class="hl-icon hl-icon-pretty"></span>Readable diagnostics</h2>
<p>See precise, per-assertion failures that keep the expected value and the actual result in view.</p>
<a href="guides/writing-tests.html#assertions-with-expect">Writing expectations <span aria-hidden="true">→</span></a>
</article>

<article class="tryke-feature-card">
<h2><span class="hl-icon hl-icon-soft"></span>Soft assertions</h2>
<p>Collect multiple assertion failures in one test so a single mismatch does not hide the rest.</p>
<a href="concepts/soft-assertions.html">Soft assertions <span aria-hidden="true">→</span></a>
</article>

<article class="tryke-feature-card">
<h2><span class="hl-icon hl-icon-async"></span>Native async support</h2>
<p>Write <code>async</code> tests and fixtures directly. There is no event-loop plugin to configure.</p>
<a href="guides/async.html">Testing async code <span aria-hidden="true">→</span></a>
</article>

<article class="tryke-feature-card">
<h2><span class="hl-icon hl-icon-watch"></span>Fast feedback</h2>
<p>Stay in watch mode while you work, or run only tests affected by the files that changed.</p>
<a href="guides/watch-mode.html">Watch mode <span aria-hidden="true">→</span></a>
</article>

<article class="tryke-feature-card">
<h2><span class="hl-icon hl-icon-fixtures"></span>Typed fixtures</h2>
<p>Compose setup and teardown with fixtures and explicit, typed <code>Depends()</code> injection.</p>
<a href="guides/writing-tests.html#fixtures">Using fixtures <span aria-hidden="true">→</span></a>
</article>

<article class="tryke-feature-card">
<h2><span class="hl-icon hl-icon-cases"></span>Expressive test structure</h2>
<p>Parametrize with <code>@test.cases</code>, group with <code>describe()</code>, and mark test outcomes clearly.</p>
<a href="concepts/cases.html">Parametrized tests <span aria-hidden="true">→</span></a>
</article>

<article class="tryke-feature-card">
<h2><span class="hl-icon hl-icon-reporters"></span>Flexible reporting</h2>
<p>Choose text, dot, JSON, JUnit, LLM, nextest-style, or pytest-sugar-style output for each workflow.</p>
<a href="guides/reporters.html">Reporters <span aria-hidden="true">→</span></a>
</article>

<article class="tryke-feature-card">
<h2><span class="hl-icon hl-icon-clientsrv"></span>Built for tooling</h2>
<p>Use persistent client/server mode to power responsive editor integrations and other test clients.</p>
<a href="concepts/client-server.html">Client/server mode <span aria-hidden="true">→</span></a>
</article>
</div>

## Quick start

Run Tryke with [uvx](https://docs.astral.sh/uv/guides/tools/)—there is
nothing to install:

```bash
uvx tryke test
```

Or, check out the [tryke playground](https://playground.tryke.dev) to try it out in your browser.

```python
from typing import Annotated

from tryke import Depends, describe, expect, fixture, test


@fixture(per="scope")
def database():
db = {}
yield db
db.clear()


with describe("users"):

@fixture
def users(database: Annotated[dict[str, dict[str, str]], Depends(database)]):
database["users"] = {}

return database["users"]

with describe("get"):

@test("returns a stored user")
async def test_get(users: Annotated[dict[str, str], Depends(users)]):
users["alice"] = "alice@example.com"

expect(users["alice"], name="returns stored email").to_equal(
"alice@example.com"
)

with describe("set"):

@test("stores a new user")
async def test_set(users: Annotated[dict[str, str], Depends(users)]):
users["bob"] = "bob@example.com"

expect(users["bob"], name="stores email under user key").to_equal(
"bob@example.com"
)

```

Run the tests:
Leave off `test` to start watch mode:

```bash
uvx tryke test # run once
uvx tryke # watch mode
uvx tryke
```

## Coming from pytest?

The [migration guide](https://tryke.dev/migration.html) has a side-by-side cheat
sheet and a
[copy-paste LLM prompt](https://tryke.dev/migration.html#migration-prompt).
## A familiar test API

## License
```python
from tryke import expect, test

This repository is licensed under the [MIT License](https://github.com/thejchap/tryke/blob/main/LICENSE).

## Installation
@test
async def test_math():
expect(40 + 2).to_equal(42)
```

See the [installation](./guides/installation.md) documentation.
Explore the [writing tests guide](guides/writing-tests.html), open the
[browser playground](https://playground.tryke.dev), or use the
[pytest migration guide](migration.html) for a side-by-side cheat sheet.
32 changes: 32 additions & 0 deletions docs/overrides/home.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{% extends "main.html" %}

{% block tabs %}
{{ super() }}
<section class="tryke-hero">
<div class="md-grid md-typeset">
<div class="tryke-hero__content">
<p class="tryke-hero__eyebrow">Rust-powered Python testing</p>
<h1>A delightful test framework for Python</h1>
<p class="tryke-hero__lead">
Tryke is a concurrent test runner with a Jest-style API, precise diagnostics,
native async support, and a fast feedback loop.
</p>
<div class="tryke-hero__actions">
<a
href="{{ 'guides/installation.html' | url }}"
class="md-button md-button--primary"
>
Get started
</a>
<a href="https://playground.tryke.dev" class="md-button">
Try the playground
</a>
</div>
</div>
</div>
</section>
{% endblock %}

{% block content %}
{{ page.content }}
{% endblock %}
6 changes: 0 additions & 6 deletions docs/overrides/main.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,13 @@
{% set og_desc = config.site_description %}
{% endif %}
{% set og_url = page.canonical_url or config.site_url %}
{% set og_image = config.extra.social_image | d(config.site_url ~ "assets/logo.png", true) %}

<meta property="og:type" content="website">
<meta property="og:site_name" content="{{ config.site_name }}">
<meta property="og:title" content="{{ og_title }}">
<meta property="og:description" content="{{ og_desc }}">
<meta property="og:url" content="{{ og_url }}">
<meta property="og:image" content="{{ og_image }}">
<meta property="og:image:alt" content="{{ config.site_name }} logo">

<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="{{ og_title }}">
<meta name="twitter:description" content="{{ og_desc }}">
<meta name="twitter:image" content="{{ og_image }}">
<meta name="twitter:image:alt" content="{{ config.site_name }} logo">
{% endblock %}
Loading
Loading