After Exporting from Novelez to Ren'Py, What Should You Automate and Play by Hand?

September 15, 2026

After Exporting from Novelez to Ren'Py, What Should You Automate and Play by Hand?

You finish a visual novel in Novelez, export it as a Ren'Py project, and make one small change in the engine. Perhaps you adjust a menu, add a platform feature, or rewrite a scene that felt too slow. The project still launches, but that does not tell you whether an older choice now reaches the wrong ending or whether a screen disappears at the right moment.

Ren'Py 8.5 added an automated testing framework for exactly this kind of repeated functional check. It can start from a known label, advance to a menu, click a choice, inspect a condition, and confirm that the game reaches the expected point. That is useful after a Novelez export because the project has crossed a boundary: it is now editable engine code, and every later engine change can affect work that was already correct.

Automation does not turn a visual novel into a fully testable machine. The practical approach is to divide the job into three layers. Let lint inspect static structure, let testcases repeat important routes, and keep reading, listening, pacing, and visual judgment in a human playthrough.

Freeze one exported baseline before adding tests

Keep the fresh export unchanged. Unzip it into a clean folder, open it with the Ren'Py SDK version you intend to use, and launch it once before editing. Confirm that the opening appears, one choice responds, media loads, and the project reaches an ending. If the untouched export already fails, adding a testcase first only records an unexplained failure.

Then duplicate that clean folder or commit it to version control. The baseline matters because Novelez remains the easier place to edit the structured story, while the exported Ren'Py project becomes a separate development line once you change its scripts or screens. A later export should not be dropped over customized engine files without a deliberate merge.

Ren'Py 8.5.3 was released on May 15, 2026, and its release announcement identifies automated testing as one of the major 8.5 additions. Use a final 8.5 release rather than a nightly build for the first test pass unless a specific fix requires otherwise. The framework exercises the running engine and needs a working graphical environment, including OpenGL, so this is not the same as a text-only script scan.

Give lint the questions it can answer

Run Ren'Py's Check Script tool before writing a route testcase. Lint looks for potential script errors and misoptimizations, and it can report problems that may appear on another platform even when the local launch seems fine. The command-line form can also return an error code when lint finds an error, which makes it useful as a simple gate before a build.

A creator inspects structural pieces before allowing the story stage to run

Lint is suited to static questions. Does a referenced image exist? Is a script statement malformed? Is a text tag left open? Did a translation entry become orphaned? The exact reports depend on the project, but the shared trait is that Ren'Py can inspect them without acting like a player through the whole route.

Do not ask lint whether a choice feels honest, whether a transition is too abrupt, or whether the affection value reaches the intended ending after four earlier decisions. Ren'Py's own developer documentation says lint is not a substitute for thorough testing. Treat a clean lint report as permission to begin behavioral testing, not as proof that the release is ready.

This separation also keeps the first failure readable. If lint reports a missing asset and an automated route later stops on the same scene, fix the static problem first. Otherwise one broken file can make several route tests fail for reasons unrelated to their choices.

Automate the routes that must survive every revision

A useful first testcase is not every possible branch. It is one route whose result should remain stable while you continue development. Choose the opening path to a common ending, a paid or unlockable route if the game has one, or a route that has broken before. Write down its starting label, the choices it clicks, and the final label or state it must reach.

Ren'Py testcases provide direct actions for that path. run Jump("label_name") begins from a known label. advance until screen "choice" moves through dialogue until a menu appears. click "Choice Text" selects an option, and assert can check a label, screen, or Python expression. Testsuites group related cases and can prepare the same starting state before each one.

A clockwork runner repeats one important route to its expected ending

Start small. One route that reliably reaches the intended ending is more valuable than a large suite whose setup nobody understands. Add the second case when it protects a different risk, such as the opposite choice at the first major branch or a load screen that must close before play resumes. Name the test after the player outcome, not after the file where it happens.

Text selectors deserve care. A testcase can click visible choice text, which is convenient, but a wording revision can then break the test even when the route remains connected. That may be the result you want if exact wording is part of the contract. If the wording is expected to change often, add stable screen element identifiers during Ren'Py customization and target those instead. The test should fail when the player behavior changes, not whenever an unrelated adjective is edited.

Automated screenshots can also compare a current screen with a stored image, with a configurable pixel difference. Use them for a few screens where composition is part of the release contract, such as the main menu or a customized choice screen. Do not capture every dialogue line. A font-rendering change, operating-system difference, or intended art revision can turn a giant screenshot collection into noise.

Do not confuse a starting shortcut with a full route

Starting a testcase from a later label is fast, but it can hide the history that makes a branch work. A variable set in chapter one will not necessarily have the right value when a test jumps directly into chapter four. Prepare required state explicitly in the test setup, or include at least one longer case that begins where the player begins.

This is also why a warp is not a replacement for a testcase. Ren'Py's developer documentation warns that warping follows one path to a target line without executing the earlier Python that would normally initialize variables. Warp is useful for opening a scene quickly while editing. A testcase is useful when you want a repeatable action sequence with a known setup and an assertion at the end.

For a Novelez export, inspect the generated labels and menu text before assuming names. The export gives you an editable Ren'Py project, but Novelez does not write the release-specific test policy for you. Once you rename labels, add custom screens, or introduce new state in Ren'Py, keep the tests beside those engine changes and rerun them after each meaningful revision.

Keep the human pass for meaning, rhythm, and devices

A test can confirm that a choice button appears and the expected ending label is reached. It cannot decide whether the choice wording prepares the player for its consequence. It can take a screenshot, but it cannot reliably tell whether the speaker's expression makes the confession feel comic instead of vulnerable. It can advance dialogue, but it does not experience a pause as suspense or delay.

Two creators check expression, sound, controls, and timing in a complete playthrough

Reserve a human pass for four kinds of evidence.

First, read the story at player speed. Check voice, repeated information, choice clarity, and whether emotional turns have enough room. Second, listen from the title screen to the ending. Confirm loop points, relative volume, abrupt cuts, and silence that was not intentional. Third, watch the complete frame on the target displays. Look for cropped faces, hard-to-read text, blocked controls, and transitions that technically finish but look wrong. Fourth, use the real input and package. Test keyboard, mouse, controller, or touch where promised, then open the distribution that players will receive rather than only the launcher project.

If the game is localized, play at least one route in each shipping language. A route testcase can prove that the translated choice remains clickable and reaches the same label. A fluent reader still needs to judge line breaks, register, names, and meaning.

Use failures to decide which layer needs a new check

When a manual playthrough finds a defect, do not automatically add a screenshot test. Ask what kind of evidence would have caught it earliest.

A missing image reference belongs to lint or a static check. A choice that reaches the wrong ending belongs to a route testcase with controlled state. A menu that sometimes fails to close belongs to a testcase that waits for the screen to disappear. Music that enters too loudly belongs to listening. A line that reveals the twist too soon belongs to editorial review.

This rule keeps the suite maintainable. Automation should protect stable behavior that a computer can observe, not collect every past disappointment. If a test fails after an intentional change, update the expectation in the same revision and explain why. If it fails unexpectedly, stop the release until you know whether the game or the test is wrong.

What should run before each release build?

Use a short, repeatable order:

  • preserve or identify the clean Novelez export baseline
  • run Ren'Py lint and resolve errors you understand
  • run the small suite of critical route testcases
  • launch the project and manually play the changed area
  • complete one start-to-ending pass for each promised platform or input family
  • build the actual distribution and smoke-test that package

The automated portion should become routine enough to run after every engine edit. The full human pass can focus on what changed and on representative complete routes, with a broader regression pass before a public release.

Novelez helps turn the story into structured scenes and choices before code becomes the main workspace. Ren'Py export opens the engine layer, and Ren'Py 8.5 makes some of the repeated checking less fragile. The handoff works best when the boundary stays honest: export a known baseline, automate stable behavior, and keep human attention on the parts of a visual novel that only a reader can judge.

Which route in your current project would cost the most trust if a later edit silently broke it, and what single assertion would prove that route still works?