diff --git a/docs/source/contributing/dev-workflow.md b/docs/source/contributing/dev-workflow.md
index fe8b70e7703385d45f7fd2d53822424b193c2592..8daac8cbd179a9922d9d70ebbcee2cd7b5dbbba2 100644
--- a/docs/source/contributing/dev-workflow.md
+++ b/docs/source/contributing/dev-workflow.md
@@ -127,18 +127,16 @@ If you think a new module is ready to be type-checked, add an exception clause t
 ## Running the Test Suite
 
 Pystencils comes with an extensive and steadily growing suite of unit tests.
-To run the testsuite, you may invoke a variant of the Nox `testsuite` session.
-There are multiple different versions of the `testsuite` session, depending on whether you are testing with our
-without CUDA, or which version of Python you wish to test with.
-You can list the available sessions using `nox -l`.
-Select one of the `testsuite` variants and run it via `nox -s "testsuite(<variant>)"`, e.g.
-```
-nox -s "testsuite(cpu)"
+To run the full testsuite, invoke the Nox `testsuite` session:
+
+```bash
+nox -s testsuite
 ```
-for the CPU-only suite.
 
-During the testsuite run, coverage information is collected and displayed using [coverage.py](https://coverage.readthedocs.io/en/7.6.10/).
-You can display a detailed overview of code coverage by opening the generated `htmlcov/index.html` page.
+:::{seealso}
+[](#testing_pystencils)
+:::
+
 
 ## Building the Documentation
 
diff --git a/docs/source/contributing/index.md b/docs/source/contributing/index.md
index 04ad821ce5eacdc2f8712ca1f666652b078b7c0f..56c97509cbc4c0e3f312fade9fd08af90c4c9c3d 100644
--- a/docs/source/contributing/index.md
+++ b/docs/source/contributing/index.md
@@ -7,6 +7,7 @@ Pystencils is an open-source package licensed under the [AGPL v3](https://www.gn
 As such, the act of contributing to pystencils by submitting a merge request is taken as agreement to the terms of the licence.
 
 :::{toctree}
-:maxdepth: 2    
+:maxdepth: 2
 dev-workflow
+testing
 :::
diff --git a/docs/source/contributing/testing.md b/docs/source/contributing/testing.md
new file mode 100644
index 0000000000000000000000000000000000000000..da8ca2d163e6af36268bbaf8f4ace5e9da850ab9
--- /dev/null
+++ b/docs/source/contributing/testing.md
@@ -0,0 +1,77 @@
+(testing_pystencils)=
+# Testing pystencils
+
+The pystencils testsuite is located at the `tests` directory,
+constructed using [pytest](https://pytest.org),
+and automated through [Nox](https://nox.thea.codes).
+On this page, you will find instructions on how to execute and extend it.
+
+## Running the Testsuite
+
+The fastest way to execute the pystencils test suite is through the `testsuite` Nox session:
+
+```bash
+nox -s testsuite
+```
+
+There exist several configurations of the testsuite session, from which the above command will
+select and execute only those that are available on your machine.
+ - *Python Versions:* The testsuite session can be run against all major Python versions between 3.10 and 3.13 (inclusive).
+   To only use a specific Python version, add the `-p 3.XX` argument to your Nox invocation; e.g. `nox -s testsuite -p 3.11`.
+ - *CuPy:* There exist three variants of `testsuite`, including or excluding tests for the CUDA GPU target: `cpu`, `cupy12` and `cupy13`.
+   To select one, append `(<variant>)` to the session name; e.g. `nox -s "testsuite(cupy12)"`.
+
+You may also pass options through to pytest via positional arguments after a pair of dashes, e.g.:
+
+```bash
+nox -s testsuite -- -k "kernelcreation"
+```
+
+During the testsuite run, coverage information is collected using [coverage.py](https://coverage.readthedocs.io/en/7.6.10/),
+and the results are exported to HTML.
+You can display a detailed overview of code coverage by opening the generated `htmlcov/index.html` page.
+
+## Extending the Test Suite
+
+### Codegen Configurations via Fixtures
+
+In the pystencils test suite, it is often necessary to test code generation features against multiple targets.
+To simplify this process, we provide a number of [pytest fixtures](https://docs.pytest.org/en/stable/how-to/fixtures.html)
+you can and should use in your tests:
+
+ - `target`: Provides code generation targets for your test.
+   Using this fixture will make pytest create a copy of your test for each target
+   available on the current machine (see {any}`Target.available_targets`).
+ - `gen_config`: Provides default code generation configurations for your test.
+   This fixture depends on `target` and provides a {any}`CreateKernelConfig` instance
+   with target-specific optimization options (in particular vectorization) enabled.
+ - `xp`: The `xp` fixture gives you either the *NumPy* (`np`) or the *CuPy* (`cp`) module,
+   depending on whether `target` is a CPU or GPU target.
+
+These fixtures are defined in `tests/fixtures.py`.
+
+### Overriding Fixtures
+
+Pytest allows you to locally override fixtures, which can be especially practical when you wish
+to restrict the target selection of a test.
+For example, the following test overrides `target` using a parametrization mark,
+and uses this in combination with the `gen_config` fixture, which now
+receives the overridden `target` parameter as input:
+
+```Python
+@pytest.mark.parametrize("target", [Target.X86_SSE, Target.X86_AVX])
+def test_bogus(gen_config):
+    assert gen_config.target.is_vector_cpu()
+```
+
+## Testing with the Experimental CPU JIT
+
+Currently, the testsuite by default still uses the {any}`legacy CPU JIT compiler <LegacyCpuJit>`,
+since the new CPU JIT compiler is still in an experimental stage.
+To test your code against the new JIT compiler, pass the `--experimental-cpu-jit` option to pytest:
+
+```bash
+nox -s testsuite -- --experimental-cpu-jit
+```
+
+This will alter the `gen_config` fixture, activating the experimental CPU JIT for CPU targets.
diff --git a/noxfile.py b/noxfile.py
index 11b3731ec8100cc4fb6c20d1e45ad6f115d35ffa..f5b20da4f4c13004bc5f640371d7fb5908e1850d 100644
--- a/noxfile.py
+++ b/noxfile.py
@@ -86,9 +86,15 @@ def typecheck(session: nox.Session):
     session.run("mypy", "src/pystencils")
 
 
-@nox.session(python=["3.10", "3.12", "3.13"], tags=["test"])
+@nox.session(python=["3.10", "3.11", "3.12", "3.13"], tags=["test"])
 @nox.parametrize("cupy_version", [None, "12", "13"], ids=["cpu", "cupy12", "cupy13"])
 def testsuite(session: nox.Session, cupy_version: str | None):
+    """Run the pystencils test suite.
+    
+    **Positional Arguments:** Any positional arguments passed to nox after `--`
+    are propagated to pytest.
+    """
+
     if cupy_version is not None:
         install_cupy(session, cupy_version, skip_if_no_cuda=True)
 
@@ -108,6 +114,7 @@ def testsuite(session: nox.Session, cupy_version: str | None):
         "--html",
         "test-report/index.html",
         "--junitxml=report.xml",
+        *session.posargs
     )
     session.run("coverage", "html")
     session.run("coverage", "xml")
diff --git a/src/pystencils/jit/cpu/cpujit_pybind11.py b/src/pystencils/jit/cpu/cpujit_pybind11.py
index a58e5bf03cfb753bf5d7c1836527f2b573b2ef22..90224b22b7405f7b48d4897071ee32b8fc7684c1 100644
--- a/src/pystencils/jit/cpu/cpujit_pybind11.py
+++ b/src/pystencils/jit/cpu/cpujit_pybind11.py
@@ -51,7 +51,7 @@ class Pybind11KernelModuleBuilder(ExtensionModuleBuilderBase):
 
         kernel_def = self._get_kernel_definition(kernel)
         kernel_args = [param.name for param in kernel.parameters]
-        includes = [f"#include {h}" for h in kernel.required_headers]
+        includes = [f"#include {h}" for h in sorted(kernel.required_headers)]
 
         from string import Template
 
@@ -76,7 +76,7 @@ class Pybind11KernelModuleBuilder(ExtensionModuleBuilderBase):
     def _get_kernel_definition(self, kernel: Kernel) -> str:
         from ...backend.emission import CAstPrinter
 
-        printer = CAstPrinter(func_prefix="inline")
+        printer = CAstPrinter()
 
         return printer(kernel)
 
diff --git a/src/pystencils/jit/cpu_extension_module.py b/src/pystencils/jit/cpu_extension_module.py
index 55f1961ca5c00963c16912ada738788688a93452..fca043db90725a441cb8b0ed9b99765c53eecb8d 100644
--- a/src/pystencils/jit/cpu_extension_module.py
+++ b/src/pystencils/jit/cpu_extension_module.py
@@ -91,12 +91,14 @@ class PsKernelExtensioNModule:
         code += "\n"
 
         #   Kernels and call wrappers
+        from ..backend.emission import CAstPrinter
+        printer = CAstPrinter(func_prefix="FUNC_PREFIX")
 
         for name, kernel in self._kernels.items():
             old_name = kernel.name
             kernel.name = f"kernel_{name}"
 
-            code += kernel.get_c_code()
+            code += printer(kernel)
             code += "\n"
             code += emit_call_wrapper(name, kernel)
             code += "\n"