Using app versions and tests#

You will learn: how to pin to a specific app version and run the test suite that ships with every app.

Prerequisites:

Every PlayMolecule app is versioned. The bare app name (proteinprepare) is always an alias for the latest installed version — convenient for exploring, brittle if you want reproducibility. This tutorial shows the pieces you need to lock down.

Setup#

from playmolecule.apps import proteinprepare

Step 1 — See available versions#

The submodule for each version lives at playmolecule.apps.<appname>.<version>:

import playmolecule.apps.proteinprepare as pp_module
print([name for name in dir(pp_module) if name.startswith("v")])

If two versions are installed you’ll see something like ['v1', 'v2']. The unqualified proteinprepare(...) symbol is aliased to whichever version sorts as latest. (See describe_apps() for the discovery API.)

Step 2 — Pin to a specific version#

To freeze your script against drift, reach into the version submodule and call its function explicitly:

ed = proteinprepare.v1.proteinprepare(outdir="out", pdbid="3ptb")

proteinprepare.v1 is the version submodule; proteinprepare.v1.proteinprepare is the dynamic function (same signature as the unqualified proteinprepare(...), just pinned). Different versions can have different parameters — pinning is the only safe way to reproduce a result across upgrades.

Step 3 — Look at built-in tests#

Every app ships a set of integration tests defined in its manifest:

print(proteinprepare.tests)

You’ll see entries like:

[simple] 'Prepare 3PTB structure from RCSB'
- Arguments:
  pdbid = 3ptb
- Expected outputs:
  output.pdb
  pka_plot.png
  details.csv

Each named test exposes a run() method.

Step 4 — Execute a test#

proteinprepare.tests.simple.run()

This runs the test in a temporary directory, waits for completion, and asserts that the expected output files exist. A 🎉 Test '<name>' succeeded in N seconds! 🎉 line means PlayMolecule and the app are correctly wired together — useful as a smoke test after installation or after update_apps().

To run a test on SLURM instead (handy for GPU-bound apps you can’t run locally):

proteinprepare.tests.simple.run(
    queue="slurm",
    dir="/shared/scratch/tests/",   # must be visible to every SLURM worker
    partition="normalCPU",
    ncpu=1,
    ngpu=0,
)

Pass dir= whenever you submit to SLURM. Without it, the test runs in /tmp/, which is node-local on most clusters — the worker won’t be able to read what your login node wrote.

Recap#

  • Each app exposes versioned submodules (app.v1, app.v2); the bare name aliases the latest.

  • Pin versions in production scripts so an update_apps() upgrade can’t silently change behaviour.

  • app.tests.<name>.run() exercises the app end-to-end. Use it as a smoke test after install or upgrade.

Next#