Skip to content

Instantly share code, notes, and snippets.

@elijahr
Last active October 15, 2025 00:05
Show Gist options
  • Select an option

  • Save elijahr/61ed5402375118a5f15f2ee96a0adfa6 to your computer and use it in GitHub Desktop.

Select an option

Save elijahr/61ed5402375118a5f15f2ee96a0adfa6 to your computer and use it in GitHub Desktop.
Bookmarklet to parse `py.test` failures from a CircleCI build page and generate a command to re-run those tests locally.

parseTestFailures.js

A bookmarklet to parse pytest failures from a CircleCI build page (tests tab).

Installation

Create a bookmark with the following URL:

javascript:(function()%7Bfunction%20requireJQuery(fn)%20%7B%0A%20%20if%20(window.jQuery)%20%7B%0A%20%20%20%20fn()%3B%0A%20%20%7D%20else%20%7B%0A%20%20%20%20if%20(!document.getElementById(%22jquery-script%22))%20%7B%0A%20%20%20%20%20%20var%20script%20%3D%20document.createElement(%22script%22)%3B%0A%20%20%20%20%20%20script.setAttribute(%22id%22%2C%20%22jquery-script%22)%3B%0A%20%20%20%20%20%20script.setAttribute(%22src%22%2C%20%22https%3A%2F%2Fcode.jquery.com%2Fjquery.js%22)%3B%0A%20%20%20%20%20%20document.getElementsByTagName(%22body%22)%5B0%5D.appendChild(script)%3B%0A%20%20%20%20%7D%0A%20%20%20%20setTimeout(requireJQuery.bind(this%2C%20fn)%2C%201000)%3B%0A%20%20%7D%0A%7D%0A%0Afunction%20parseTestFailures()%20%7B%0A%20%20var%20%24%20%3D%20window.jQuery%3B%0A%20%20var%20tests%20%3D%20new%20Set()%3B%0A%0A%20%20%24(%22%5Bdata-testid%3Dtest-result-title%5D%22).each(function%20()%20%7B%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20var%20title%20%3D%20%24(this).text()%3B%0A%20%20%20%20%20%20var%20mod%20%3D%20%24(this).parent().parent().children().eq(-1).text()%3B%0A%20%20%20%20%20%20if%20(mod.toLowerCase()%20%3D%3D%3D%20mod)%20%7B%0A%20%20%20%20%20%20%20%20var%20modPath%20%3D%20mod.split(%22.%22).join(%22%2F%22)%20%2B%20%22.py%22%3B%0A%20%20%20%20%20%20%20%20tests.add(%60%24%7BmodPath%7D%3A%3A%24%7Btitle%7D%60)%3B%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20var%20modPath%20%3D%20mod.split(%22.%22).slice(0%2C%20-1).join(%22%2F%22)%20%2B%20%22.py%22%3B%0A%20%20%20%20%20%20%20%20var%20className%20%3D%20mod.split(%22.%22).slice(-1)%5B0%5D%3B%0A%20%20%20%20%20%20%20%20tests.add(%60%24%7BmodPath%7D%3A%3A%24%7BclassName%7D%3A%3A%24%7Btitle%7D%60)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%20catch%20(err)%20%7B%7D%0A%20%20%7D)%3B%0A%0A%20%20console.log(Array.from(tests).join('%5Cn'))%3B%0A%7D%0A%0ArequireJQuery(parseTestFailures)%3B%7D)()%3B

Usage

Visit a CircleCI build page representing a py.test run. Click the bookmark. An alert box will display with content such as the following:

function requireJQuery(fn) {
if (window.jQuery) {
fn();
} else {
if (!document.getElementById("jquery-script")) {
var script = document.createElement("script");
script.setAttribute("id", "jquery-script");
script.setAttribute("src", "https://code.jquery.com/jquery.js");
document.getElementsByTagName("body")[0].appendChild(script);
}
setTimeout(requireJQuery.bind(this, fn), 1000);
}
}
function parseTestFailures() {
var $ = window.jQuery;
var tests = new Set();
$("[data-testid=test-result-title]").each(function () {
try {
var title = $(this).text();
var mod = $(this).parent().parent().children().eq(-1).text();
if (mod.toLowerCase() === mod) {
var modPath = mod.split(".").join("/") + ".py";
tests.add(`${modPath}::${title}`);
} else {
var modPath = mod.split(".").slice(0, -1).join("/") + ".py";
var className = mod.split(".").slice(-1)[0];
tests.add(`${modPath}::${className}::${title}`);
}
} catch (err) {}
});
console.log(Array.from(tests).join('\n'));
}
requireJQuery(parseTestFailures);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment