Faster Pyodide Testing#
We’re going to do a lot of “sit in JS, execute Python.” We want to speed it up. Let’s change our test strategy to re-use a single Pyodide across many tests.
Clean up worker tests#
We have a test that asserts the JS initialize
function returns some flag.
Actually, it’s going to return the Pyodide instance.
Let’s re-organize our worker tests:
import {beforeEach, expect, test} from "vitest";
import {initialize} from "../src/pyodide_components/worker.js";
// Make an interpreter and capture its startup state
const thisPyodide = await initialize();
const initialPyodideState = thisPyodide.pyodide_py._state.save_state();
beforeEach(async () => {
// On each test, reset to an "empty" interpreter
thisPyodide.pyodide_py._state.restore_state(initialPyodideState);
});
test("Load and initialize Pyodide", () => {
expect(typeof thisPyodide.runPythonAsync).to.equal("function");
});
test("Confirm valid and running Pyodide", async () => {
const result = await thisPyodide.runPythonAsync("1+1");
expect(result).to.equal(2);
});
Lots of changes here.
First, the two lines about thisPyodide
.
We make a Pyodide instance a module scope, then immediately capture its default startup state.
In beforeEach
, we speed up our test runs.
Instead of making a new interpreter all the time, we re-use the existing one.
But we reset it to its initial state.
We then split our tests into two parts: did we actually get a Pyodide, and does it run Python code?
Worker returns a pyodide
#
Over in our initialize
function, for now, just return Pyodide:
import {loadPyodide} from "./pyodide/pyodide.mjs";
export async function initialize() {
return await loadPyodide();
}
Wrapup#
We’re already in a neat spot. We can sit in a test, in a debugger, in our smart editor – and evaluate Python from JS.