Repository: PlasmaPy/PlasmaPy

Issue:
Update testing guide to reflect that repeat runs of tox are only a few seconds slower than pytest
The testing guide currently states that running tests with tox is slower because it needs to recreate an environment. More recent versions of tox are doing a better job at caching environments, so I'm finding now that running tests locally with tox is only about 3 seconds longer than running tests with pytest, except for the first tox run when it needs to recreate the environment.  Running tox also makes sure that the tests are done in a consistent environment, so I think we should recommend tox as the recommended way to run tests nowadays.  

(Incidentally, we might be able to use a tox-uv plugin which would speed up the creation of environments, but that's a separate issue.)


Discussion:

Resolving patch:
diff --git a/docs/_global_substitutions.py b/docs/_global_substitutions.py
--- a/docs/_global_substitutions.py
+++ b/docs/_global_substitutions.py
@@ -85,6 +85,7 @@
     "lite-functions": r":term:`lite-functions`\ ",
     "maxpython": "3.12",
     "minpython": "3.10",
+    "open a terminal": r":ref:`open a terminal <opening-a-terminal>`\ ",
     "Open a terminal": r":ref:`Open a terminal <opening-a-terminal>`\ ",
     "parameter": r":term:`parameter`\ ",
     "parameters": r":term:`parameters <parameter>`\ ",


Test patch:
diff --git a/docs/contributing/testing_guide.rst b/docs/contributing/testing_guide.rst
--- a/docs/contributing/testing_guide.rst
+++ b/docs/contributing/testing_guide.rst
@@ -12,48 +12,62 @@ Testing Guide
 Summary
 =======
 
-* New functionality added to PlasmaPy must have tests.
+Running tests
+-------------
 
-* Tests are located in the top-level |tests/| directory. For example,
-  tests of `plasmapy.formulary` are in :file:`tests/formulary/`.
+To prepare to run tests from the command line, |open a terminal| and
+install |tox| with its extensions:
 
-* The names of test files begin with :file:`test_`.
+.. tabs::
 
-* Tests are either functions beginning with :py:`test_` or classes
-  beginning with :py:`Test`.
+   .. group-tab:: macOS, Linux, or WSL
 
-* Here is an example of a minimal `pytest` test that uses an
-  :py:`assert` statement:
+      .. code-block:: console
 
-  .. code-block:: python
+         python -m pip install tox tox-uv
 
-      def test_multiplication():
-          assert 2 * 3 == 6
+   .. group-tab:: Windows
+
+      .. code-block:: console
+
+         py -m pip install tox tox-uv
+
+To run tests, navigate to a directory within your local clone of
+PlasmaPy and run:
+
+.. code-block:: console
 
-* To install the packages needed to run the tests:
+   tox
 
-  - Open a terminal.
+This command will invoke `pytest` to run PlasmaPy's tests, excluding the
+tests marked as slow.
 
-  - Navigate to the top-level directory (probably named
-    :file:`PlasmaPy/`) in your local clone of PlasmaPy's repository.
+.. important::
 
-  - If you are on macOS or Linux, run:
+   PlasmaPy is in the process of switching its test runner from |tox| to
+   |nox|. In the near future, it will likely be necessary to run ``nox``
+   instead of ``tox`` to invoke tests.
 
-    .. code-block:: console
+Writing tests
+-------------
+
+* All functionality in PlasmaPy must have tests.
 
-       python -m pip install -e ".[tests]"
+* Tests are located in the top-level |tests/| directory. For example,
+  tests of `plasmapy.formulary` are in :file:`tests/formulary/`.
 
-    If you are on Windows, run:
+* The names of test files begin with :file:`test_`.
 
-    .. code-block:: console
+* Tests are either functions beginning with :py:`test_` or classes
+  beginning with :py:`Test`.
 
-       py -m pip install -e .[tests]
+* Here is an example of a minimal `pytest` test that uses an
+  :py:`assert` statement:
 
-    These commands will perform an |editable installation| of your
-    local clone of PlasmaPy.
+  .. code-block:: python
 
-* Run `pytest` in the command line in order to run tests in that
-  directory and its subdirectories.
+      def test_multiplication():
+          assert 2 * 3 == 6
 
 Introduction
 ============
@@ -533,20 +547,13 @@ PlasmaPy's tests can be run in the following ways:
 4. Running tests from an :wikipedia:`integrated development environment
    <integrated_development_environment>` (IDE).
 
-We recommend that new contributors perform the tests via a pull request
-on |GitHub|. Creating a draft pull request and keeping it updated will
-ensure that the necessary checks are run frequently. This approach is
-also appropriate for pull requests with a limited scope. This advantage
-of this approach is that the tests are run automatically and do not
-require any extra work. The disadvantages are that running the tests on
-|GitHub| is often slow and that navigating the test results is sometimes
-difficult.
-
-We recommend that experienced contributors run tests either by using
-`pytest` from the command line or by using your preferred IDE. Using |tox|
-is an alternative to `pytest`, but running tests with |tox| adds the
-overhead of creating an isolated environment for your test and can thus
-be slower.
+We recommend that new contributors perform tests via a pull request on
+GitHub. Creating a draft pull request and keeping it updated ensures
+that all necessary checks are run frequently.
+
+Experienced contributors may find it useful to run tests from the
+command line using `pytest` or |tox|, or via an IDE. In particular,
+using |tox| ensures that tests are run in the same way as in CI.
 
 Using GitHub
 ------------
@@ -652,7 +659,7 @@ The following checks are performed with each pull request.
 
 .. note::
 
-   The continuous integration checks performed for pull requests change
+   The continuous integration (CI) checks performed for pull requests change
    frequently. If you notice that the above list has become out-of-date,
    please `submit an issue that this section needs updating
    <https://github.com/PlasmaPy/PlasmaPy/issues/new?title=Update%20information%20on%20GitHub%20checks%20in%20testing%20guide&labels=Documentation>`__.
@@ -663,14 +670,14 @@ Using pytest
 To install the packages necessary to run tests on your local computer
 (including |tox| and pytest_), run:
 
-.. code-block:: shell
+.. code-block:: console
 
    pip install -e .[tests]
 
 To run PlasmaPy's tests from the command line, go to a directory within
 PlasmaPy's repository and run:
 
-.. code-block:: shell
+.. code-block:: console
 
    pytest
 
@@ -682,7 +689,7 @@ particular file or directory, include its name after `pytest`. If you
 are in the directory :file:`plasmapy/particles/tests/`, then the tests
 in in :file:`test_atomic.py` can be run with:
 
-.. code-block:: shell
+.. code-block:: console
 
    pytest test_atomic.py
 
@@ -713,13 +720,21 @@ PlasmaPy's continuous integration tests on |GitHub| are typically run
 using |tox|, a tool for automating Python testing. Using |tox| simplifies
 testing PlasmaPy with different releases of Python, with different
 versions of PlasmaPy's dependencies, and on different operating systems.
-While testing with |tox| is more robust than testing with `pytest`, using
-|tox| to run tests is typically slower because |tox| creates its own
-virtual environments.
+Testing with |tox| is more robust than testing with `pytest` because
+|tox| creates its own virtual environments and ensures that tests are
+run the same way as in CI. The ``tox-uv`` extension lets |tox| use |uv|
+as its back-end for significantly improved dependency resolution and
+caching.
+
+To run PlasmaPy's tests (except for those marked as slow), run:
+
+.. code-block:: console
+
+   tox
 
 To run PlasmaPy's tests for a particular environment, run:
 
-.. code-block:: shell
+.. code-block:: console
 
    tox -e ⟨envname⟩
 
@@ -727,25 +742,24 @@ where ``⟨envname⟩`` is replaced with the name of the |tox| environment,
 as described below.
 
 Some testing environments for |tox| are pre-defined. For example, you
-can replace ``⟨envname⟩`` with ``py39`` if you are running Python
-``3.9.x``, ``py310`` if you are running Python ``3.10.x``, or ``py311``
-if you are running Python ``3.11.x``. Running |tox| with any of these
+can replace ``⟨envname⟩`` with ``py310`` if you are running Python
+``3.10.x``, ``py311`` if you are running Python ``3.11.x``, or ``py312``
+if you are running Python ``3.12.x``. Running |tox| with any of these
 environments requires that the appropriate version of Python has been
 installed and can be found by |tox|. To find the version of Python that
-you are using, go to the command line and run ``python
---version``.
+you are using, go to the command line and run ``python --version``.
 
 Additional `tox environments`_ are defined in :file:`tox.ini` in the
 top-level directory of PlasmaPy's repository. To find which testing
 environments are available, run:
 
-.. code-block:: shell
+.. code-block:: console
 
    tox -a
 
 For example, static type checking with |mypy| can be run locally with
 
-.. code-block:: shell
+.. code-block:: console
 
    tox -e mypy
 
@@ -797,7 +811,7 @@ Code coverage reports may be generated on your local computer to show
 which lines of code are covered by tests and which are not. To generate
 an HTML report, use the ``--cov`` flag for `pytest`:
 
-.. code-block:: shell
+.. code-block:: console
 
    pytest --cov
    coverage html