diff --git a/.markdownlint-cli2.yaml b/.markdownlint-cli2.yaml index 11f1b27..b619bb1 100644 --- a/.markdownlint-cli2.yaml +++ b/.markdownlint-cli2.yaml @@ -8,8 +8,11 @@ config: MD033: allowed_elements: - a + - article - code + - div - h1 + - h2 - img - li - p diff --git a/README.md b/README.md index 5a45ae2..e487f0d 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,7 @@ -

- - tryke-small - -

Tryke

ruff PyPI license python CI docs

- - ## Highlights - [Fast](https://tryke.dev/concepts/discovery.html) Rust-powered test discovery diff --git a/docs/assets/logo.png b/docs/assets/logo.png deleted file mode 100644 index f7534db..0000000 Binary files a/docs/assets/logo.png and /dev/null differ diff --git a/docs/index.md b/docs/index.md index d4a876a..7bedd82 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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 +---

@@ -23,99 +28,94 @@ A Rust-based Python test runner with a Jest-style API.

- - -## Highlights - - - -## Getting started - -Run tryke with [uvx](https://docs.astral.sh/uv/guides/tools/) to get started quickly: +
+
+

Fast discovery

+

Let Rust find your Python tests quickly, with cached discovery built for tight feedback loops.

+ How discovery works +
+ +
+

Concurrent by default

+

Run independent tests in parallel without opting into a separate plugin or changing your suite.

+ Concurrency model +
+ +
+

Readable diagnostics

+

See precise, per-assertion failures that keep the expected value and the actual result in view.

+ Writing expectations +
+ +
+

Soft assertions

+

Collect multiple assertion failures in one test so a single mismatch does not hide the rest.

+ Soft assertions +
+ +
+

Native async support

+

Write async tests and fixtures directly. There is no event-loop plugin to configure.

+ Testing async code +
+ +
+

Fast feedback

+

Stay in watch mode while you work, or run only tests affected by the files that changed.

+ Watch mode +
+ +
+

Typed fixtures

+

Compose setup and teardown with fixtures and explicit, typed Depends() injection.

+ Using fixtures +
+ +
+

Expressive test structure

+

Parametrize with @test.cases, group with describe(), and mark test outcomes clearly.

+ Parametrized tests +
+ +
+

Flexible reporting

+

Choose text, dot, JSON, JUnit, LLM, nextest-style, or pytest-sugar-style output for each workflow.

+ Reporters +
+ +
+

Built for tooling

+

Use persistent client/server mode to power responsive editor integrations and other test clients.

+ Client/server mode +
+
+ +## 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. diff --git a/docs/overrides/home.html b/docs/overrides/home.html new file mode 100644 index 0000000..f873f6f --- /dev/null +++ b/docs/overrides/home.html @@ -0,0 +1,32 @@ +{% extends "main.html" %} + +{% block tabs %} + {{ super() }} +
+
+
+

Rust-powered Python testing

+

A delightful test framework for Python

+

+ Tryke is a concurrent test runner with a Jest-style API, precise diagnostics, + native async support, and a fast feedback loop. +

+ +
+
+
+{% endblock %} + +{% block content %} + {{ page.content }} +{% endblock %} diff --git a/docs/overrides/main.html b/docs/overrides/main.html index cba3491..b68f882 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -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) %} - - - - - {% endblock %} diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index f548f5d..f589976 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -30,10 +30,85 @@ --tab-icon: url("../assets/icons/file-code.svg"); } +/* Home page hero. */ +.tryke-hero { + padding: 4.5rem 1rem; + background: + radial-gradient(circle at 50% 0%, rgb(30 130 120 / 35%), transparent 42%), + #064b47; +} + +.tryke-hero__content { + max-width: 42rem; + margin: 0 auto; + text-align: center; +} + +.tryke-hero__eyebrow { + margin: 0 0 0.8rem; + color: rgb(188 240 233 / 85%); + font-size: 0.72rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.tryke-hero__content h1 { + margin: 0; + color: #fff; + font-size: clamp(2.25rem, 6vw, 3.4rem); + font-weight: 500; + letter-spacing: -0.045em; + line-height: 1.08; +} + +.tryke-hero__lead { + max-width: 36rem; + margin: 1.2rem auto 0; + color: rgb(255 255 255 / 75%); + font-size: 1.08rem; + line-height: 1.65; +} + +.tryke-hero__actions { + display: flex; + flex-wrap: wrap; + gap: 0.6rem; + justify-content: center; + margin-top: 1.75rem; +} + +.tryke-hero .md-button { + min-width: 7.5rem; + color: #fff; + border-color: rgb(255 255 255 / 80%); +} + +.tryke-hero .md-button:hover, +.tryke-hero .md-button:focus { + color: #fff; + background: rgb(255 255 255 / 12%); + border-color: #fff; +} + +.tryke-hero .md-button--primary { + color: #064b47; + background: #fff; + border-color: #fff; +} + +.tryke-hero .md-button--primary:hover, +.tryke-hero .md-button--primary:focus { + color: #064b47; + background: rgb(255 255 255 / 85%); + border-color: rgb(255 255 255 / 85%); +} + /* Demoted shields.io badges below the hero. */ .md-badges { - margin-top: 1.25rem; - opacity: 0.8; + margin: 0.5rem 0 1.5rem; + text-align: center; + opacity: 0.78; } .md-badges a { @@ -42,14 +117,13 @@ border-bottom: none; } -/* Highlights list icons. The icon class travels with each
  • so - reordering the list does not require touching CSS. */ +/* Feature card icons. */ .hl-icon { display: inline-block; - width: 1.1em; - height: 1.1em; - margin-right: 0.5em; - vertical-align: -0.2em; + width: 1.25em; + height: 1.25em; + margin-right: 0.45em; + vertical-align: -0.25em; background-color: var(--md-primary-fg-color); -webkit-mask: var(--hl-icon) center / contain no-repeat; mask: var(--hl-icon) center / contain no-repeat; @@ -72,20 +146,60 @@ .hl-icon-marks { --hl-icon: url("../assets/icons/tag.svg"); } .hl-icon-describe { --hl-icon: url("../assets/icons/folder-tree.svg"); } -/* Drop bullet markers on the highlights list since icons replace them. - Material's content rules use a higher-specificity selector so qualify - ours with `ul.md-highlights` to win. */ -ul.md-highlights { - list-style: none; - padding-left: 0; - margin-left: 0; +.tryke-feature-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0.8rem; + margin: 0 0 3rem; } -ul.md-highlights > li { - margin-bottom: 0.4em; - list-style: none; +.tryke-feature-card { + display: flex; + flex-direction: column; + min-width: 0; + padding: 1.2rem; + border: 0.05rem solid var(--md-default-fg-color--lightest); + border-radius: 0.2rem; + box-shadow: 0 0.1rem 0.2rem rgb(0 0 0 / 7%); + transition: + border-color 125ms, + box-shadow 125ms, + transform 125ms; } -ul.md-highlights > li::marker { - content: ""; +.tryke-feature-card:hover { + border-color: var(--md-accent-fg-color); + box-shadow: 0 0.2rem 0.5rem rgb(0 0 0 / 12%); + transform: translateY(-0.05rem); +} + +.tryke-feature-card h2 { + margin: 0; + color: var(--md-default-fg-color); + font-size: 0.9rem; + font-weight: 700; + letter-spacing: -0.01em; + line-height: 1.4; +} + +.tryke-feature-card p { + flex: 1; + margin: 0.75rem 0; + padding-top: 0.75rem; + border-top: 0.05rem solid var(--md-default-fg-color--lightest); + color: var(--md-default-fg-color--light); +} + +.tryke-feature-card > a { + font-weight: 600; +} + +@media screen and (max-width: 44.984375rem) { + .tryke-hero { + padding: 3.25rem 1rem; + } + + .tryke-feature-grid { + grid-template-columns: 1fr; + } } diff --git a/playground/index.html b/playground/index.html index 2aa41ac..f9d98cf 100644 --- a/playground/index.html +++ b/playground/index.html @@ -3,7 +3,6 @@ - Tryke Playground diff --git a/playground/public/logo.png b/playground/public/logo.png deleted file mode 100644 index f7534db..0000000 Binary files a/playground/public/logo.png and /dev/null differ diff --git a/playground/src/Editor/Chrome.tsx b/playground/src/Editor/Chrome.tsx index 177636b..dec5946 100644 --- a/playground/src/Editor/Chrome.tsx +++ b/playground/src/Editor/Chrome.tsx @@ -298,8 +298,7 @@ export function Chrome() {
    {/* Toolbar */}
    - - tryke +

    Tryke Playground

    {wasmVersion && ( diff --git a/zensical.toml b/zensical.toml index b298a27..c20c10f 100644 --- a/zensical.toml +++ b/zensical.toml @@ -45,8 +45,6 @@ repo = "fontawesome/brands/github" [project.theme] custom_dir = "docs/overrides" -logo = "assets/logo.png" -favicon = "assets/logo.png" features = [ "navigation.instant", "navigation.sections", @@ -87,11 +85,6 @@ toggle.name = "Switch to system preference" primary = "teal" accent = "teal" -# Absolute URL to the thumbnail rendered when the site is pasted into -# Slack / LinkedIn / Twitter / Discord. Consumed by docs/overrides/main.html. -[project.extra] -social_image = "https://tryke.dev/assets/logo.png" - [[project.extra.social]] icon = "fontawesome/brands/github" link = "https://github.com/thejchap"