A quick guide to running NixOS tests interactively like you would in other testing framework.

  1. Insert the following line where you’d like to interact in testScript:

    breakpoint()
    
  2. Build and run the test driver for your test after replacing TEST with your actual test name:

    "$(nix-build -A nixosTests.TEST.driver)/bin/nixos-test-driver"
    

Once you get a Python debugger prompt like (Pdb) you’re in an interactive Python shell, and can run Python commands interactively. This terminal unfortunately does not have auto-complete enabled, but it does support discovery via the ? special command:

(Pdb) ?

Documented commands (type help <topic>):
========================================
EOF    c          d        h         list      q        rv       undisplay
a      cl         debug    help      ll        quit     s        unt
alias  clear      disable  ignore    longlist  r        source   until
args   commands   display  interact  n         restart  step     up
b      condition  down     j         next      return   tbreak   w
break  cont       enable   jump      p         retval   u        whatis
bt     continue   exit     l         pp        run      unalias  where

⚠ Machine logs will continue to print to your terminal after the prompt shows up! You can try the example session below to see this in action. If you suspect that the prompt has been buried in logs, just press Enter. If you’ve not yet reached the prompt it should simply draw an empty line.

You can also get into an interactive shell on any of the nodes you have started by running the following after replacing NODE with your node name:

NODE.shell_interact()

Once you’re done, exit with Ctrl-d like you would a normal shell to get back into the Python debugger.

Once you’re done in the Python debugger, either run continue to finish running the tests or press Ctrl-d to cancel the test run.

Example session

Using current nixpkgs:

  1. Add a breakpoint after starting all the machines in the SSH audit test:

    sed --in-place --expression='/start_all()/a\      breakpoint()' nixos/tests/ssh-audit.nix
    
  2. Run the test:

    "$(nix-build -A nixosTests.ssh-audit.driver)/bin/nixos-test-driver"
    
  3. Wait for the output to quieten down.
  4. Press Enter to re-draw the Python debugger prompt.
  5. Run server.shell_interact() to start Bash in the server VM.
  6. Run hostname to verify that you’re indeed on the server VM.
  7. Press Ctrl-d to return to the Python debugger prompt.
  8. Press Ctrl-d again to end debugging.
  9. Remove the SSH audit test breakpoint:

    sed --in-place --expression='/      breakpoint()/d' nixos/tests/ssh-audit.nix
    

⚠ Interactivity broke for me in weird ways during testing. Once after exiting Bash I got a new Bash prompt rather than going back to the Python debugger, and the shell seemed to be broken. Another time the shell would no longer show any of my input, but did show command output. Another user mentioned how pressing either Ctrl-c or Ctrl-d could cause the entire session to end from within shell_interact(). This points to some broken signal handling, so try to be careful with using the minimum amount of Ctrl-c/Ctrl-d while debugging. And if anything like this happens, you’ll probably want to run reset once you get back to your native shell. Update: I’ve reported the easily reproducible findings.

Sources & more info