<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://usamaJ17.github.io/pytest-web/blog</id>
    <title>pytest-web Blog</title>
    <updated>2026-05-07T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://usamaJ17.github.io/pytest-web/blog"/>
    <subtitle>pytest-web Blog</subtitle>
    <icon>https://usamaJ17.github.io/pytest-web/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[Stop editing your test files just to run a subset — use pytest-web instead]]></title>
        <id>https://usamaJ17.github.io/pytest-web/blog/introducing-pytest-web</id>
        <link href="https://usamaJ17.github.io/pytest-web/blog/introducing-pytest-web"/>
        <updated>2026-05-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[pytest-web gives you a browser UI for running pytest — pick exact tests, watch live results, re-run only failures, and open Allure reports in one click. No more editing files or memorising node IDs.]]></summary>
        <content type="html"><![CDATA[<p>You've been there. You have a test file with 40 parametrized cases. You need to run 3 of them. So you open the file, comment out the ones you don't want, run pytest, then uncomment everything again. Or you try to remember the exact <code>-k</code> expression. Or you copy-paste a node ID from the terminal and hope you got it right.</p>
<p>There's a better way.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-pytest-web">What is pytest-web?<a href="https://usamaj17.github.io/pytest-web/blog/introducing-pytest-web#what-is-pytest-web" class="hash-link" aria-label="Direct link to What is pytest-web?" title="Direct link to What is pytest-web?" translate="no">​</a></h2>
<p>pytest-web is a local web UI that sits on top of your existing pytest setup. You run one command, a browser tab opens, and from there you can see all your tests, pick exactly which ones to run, watch them pass or fail in real time, and re-run failures with a single click.</p>
<p>It doesn't replace pytest. It doesn't touch your <code>conftest.py</code> or your fixtures. It just wraps the same <code>pytest</code> command you already use and gives you a visual layer on top.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="getting-started-takes-30-seconds">Getting started takes 30 seconds<a href="https://usamaj17.github.io/pytest-web/blog/introducing-pytest-web#getting-started-takes-30-seconds" class="hash-link" aria-label="Direct link to Getting started takes 30 seconds" title="Direct link to Getting started takes 30 seconds" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">pip </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> pytest-web</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">cd</span><span class="token plain"> your-project</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pytest-web</span><br></div></code></pre></div></div>
<p>That's it. A browser tab opens at <code>http://127.0.0.1:8000</code>. Your project's <code>pytest.ini</code>, fixtures, and plugins are all picked up automatically — nothing to configure.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-parametrize-problem-solved">The parametrize problem, solved<a href="https://usamaj17.github.io/pytest-web/blog/introducing-pytest-web#the-parametrize-problem-solved" class="hash-link" aria-label="Direct link to The parametrize problem, solved" title="Direct link to The parametrize problem, solved" translate="no">​</a></h2>
<p>Here's the situation that motivated this tool. Say you have this in your test file:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token decorator annotation punctuation" style="color:#393A34">@pytest</span><span class="token decorator annotation punctuation" style="color:#393A34">.</span><span class="token decorator annotation punctuation" style="color:#393A34">mark</span><span class="token decorator annotation punctuation" style="color:#393A34">.</span><span class="token decorator annotation punctuation" style="color:#393A34">parametrize</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"browser,env"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"chrome"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">  </span><span class="token string" style="color:#e3116c">"staging"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"chrome"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">  </span><span class="token string" style="color:#e3116c">"production"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"firefox"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"staging"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"firefox"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"production"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"safari"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">  </span><span class="token string" style="color:#e3116c">"staging"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"safari"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">  </span><span class="token string" style="color:#e3116c">"production"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">test_checkout_flow</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">browser</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> env</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><br></div></code></pre></div></div>
<p>Six variants. You've just pushed a fix and you only want to run the two <code>production</code> ones to verify.</p>
<p><strong>Before pytest-web:</strong> comment out 4 parametrize entries, run pytest, uncomment them. Or write <code>-k "production"</code> and hope that expression doesn't accidentally catch something else.</p>
<p><strong>With pytest-web:</strong> click <strong>Fetch Tests</strong>. Every variant appears as its own row:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">✅  test_checkout_flow[chrome-staging]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">✅  test_checkout_flow[chrome-production]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">✅  test_checkout_flow[firefox-staging]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">✅  test_checkout_flow[firefox-production]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">✅  test_checkout_flow[safari-staging]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">✅  test_checkout_flow[safari-production]</span><br></div></code></pre></div></div>
<p>Uncheck the four staging ones. Click <strong>▶ Run Selected</strong>. Done. Your file is untouched.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="watch-results-in-real-time">Watch results in real time<a href="https://usamaj17.github.io/pytest-web/blog/introducing-pytest-web#watch-results-in-real-time" class="hash-link" aria-label="Direct link to Watch results in real time" title="Direct link to Watch results in real time" translate="no">​</a></h2>
<p>While tests run, each row shows a pulsing dot. As each test finishes it turns:</p>
<ul>
<li class="">🟢 Green — passed</li>
<li class="">🔴 Red — failed</li>
<li class="">🟡 Yellow — skipped</li>
</ul>
<p>You don't wait for the whole suite to finish. You see results as they happen. If something fails early you already know while the rest are still running.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="re-run-only-the-failures">Re-run only the failures<a href="https://usamaj17.github.io/pytest-web/blog/introducing-pytest-web#re-run-only-the-failures" class="hash-link" aria-label="Direct link to Re-run only the failures" title="Direct link to Re-run only the failures" translate="no">​</a></h2>
<p>This is the feature people end up using the most.</p>
<p>After a run, click the <strong>failed</strong> counter at the top. The view filters to show only failed tests. Click <strong>▶ Run Selected</strong>. Only those tests run — nothing else.</p>
<p>No <code>-k</code> expression. No copy-pasting node IDs. No editing any file. Just two clicks.</p>
<p>This loop — run → filter to failed → fix → re-run failures — is where pytest-web saves the most time day to day.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="run-tests-in-parallel">Run tests in parallel<a href="https://usamaj17.github.io/pytest-web/blog/introducing-pytest-web#run-tests-in-parallel" class="hash-link" aria-label="Direct link to Run tests in parallel" title="Direct link to Run tests in parallel" translate="no">​</a></h2>
<p>Set the <strong>Workers</strong> field to any number and pytest-web runs your suite with <code>pytest-xdist</code> automatically. No config changes needed:</p>
<ul>
<li class="">Workers: <code>1</code> → normal sequential run</li>
<li class="">Workers: <code>4</code> → 4 parallel processes</li>
</ul>
<p>pytest-xdist is installed as a dependency, so it's already there. pytest-web handles all the complexity of deduplicating events from parallel workers so the UI stays correct.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="inject-env-vars-without-touching-your-shell">Inject env vars without touching your shell<a href="https://usamaj17.github.io/pytest-web/blog/introducing-pytest-web#inject-env-vars-without-touching-your-shell" class="hash-link" aria-label="Direct link to Inject env vars without touching your shell" title="Direct link to Inject env vars without touching your shell" translate="no">​</a></h2>
<p>Need to run tests against a different environment? Use the <strong>Env Vars</strong> panel:</p>
<table><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody><tr><td><code>ENV</code></td><td><code>staging</code></td></tr><tr><td><code>API_URL</code></td><td><code>https://api.staging.example.com</code></td></tr></tbody></table>
<p>Variables are saved to localStorage and restored on page reload. Type <code>NAME=value</code> in the Name field and it auto-splits — no need to fill both columns separately.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="allure-reports-in-one-click">Allure reports in one click<a href="https://usamaj17.github.io/pytest-web/blog/introducing-pytest-web#allure-reports-in-one-click" class="hash-link" aria-label="Direct link to Allure reports in one click" title="Direct link to Allure reports in one click" translate="no">​</a></h2>
<p>If you use Allure for test reporting, pytest-web has you covered. After your tests run:</p>
<ol>
<li class="">Click <strong>Open Report</strong> in the Allure bar at the bottom</li>
<li class="">pytest-web generates the report and opens it in your browser automatically</li>
<li class="">Every time you regenerate, history is carried forward — so trend graphs and retry counts work out of the box</li>
</ol>
<p>No commands to remember. No manual <code>allure generate &amp;&amp; allure open</code>. Just one click.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="everything-you-need-nothing-you-dont">Everything you need, nothing you don't<a href="https://usamaj17.github.io/pytest-web/blog/introducing-pytest-web#everything-you-need-nothing-you-dont" class="hash-link" aria-label="Direct link to Everything you need, nothing you don't" title="Direct link to Everything you need, nothing you don't" translate="no">​</a></h2>
<p>Here's the full feature list — and notice how short it is:</p>
<table><thead><tr><th>Feature</th><th>How it works</th></tr></thead><tbody><tr><td>Fetch tests</td><td>Click "Fetch Tests" or press Enter</td></tr><tr><td>Select/deselect</td><td>Checkboxes per test or per file</td></tr><tr><td>Filter by name</td><td>Type in the search box</td></tr><tr><td>Filter by outcome</td><td>Click passed / failed / skipped counter</td></tr><tr><td>Parallel workers</td><td>Set the number in the Workers field</td></tr><tr><td>Custom pytest args</td><td>Type in the args bar or use the param builder dropdown</td></tr><tr><td>Env var injection</td><td>Add rows in the Env Vars panel</td></tr><tr><td>Live output log</td><td>Collapsible panel at the bottom, opens on errors</td></tr><tr><td>Copy command</td><td>Click ⎘ to copy the exact pytest command</td></tr><tr><td>Allure report</td><td>Click "Open Report" in the Allure bar</td></tr><tr><td>Dark mode</td><td>Theme switcher in the top right</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="try-it-now">Try it now<a href="https://usamaj17.github.io/pytest-web/blog/introducing-pytest-web#try-it-now" class="hash-link" aria-label="Direct link to Try it now" title="Direct link to Try it now" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">pip </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> pytest-web</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">cd</span><span class="token plain"> your-project</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pytest-web</span><br></div></code></pre></div></div>
<p>If you run into anything or have a feature idea, <a href="https://github.com/usamaJ17/pytest-web/issues" target="_blank" rel="noopener noreferrer" class="">open an issue on GitHub</a>. The project is MIT licensed and contributions are very welcome.</p>]]></content>
        <author>
            <name>Usama Jalal</name>
            <uri>https://github.com/usamaJ17</uri>
        </author>
        <category label="pytest" term="pytest"/>
        <category label="testing" term="testing"/>
        <category label="python" term="python"/>
        <category label="developer tools" term="developer tools"/>
        <category label="allure" term="allure"/>
    </entry>
</feed>