From 29ed6619f330a6573010a39fa35ba57c153dd4b1 Mon Sep 17 00:00:00 2001 From: James Cooke Date: Wed, 10 May 2023 22:50:40 +0100 Subject: [PATCH] Add docs on Large style Act blocks (#219) --- CHANGELOG.rst | 3 ++ README.rst | 10 +++- docs/compatibility.rst | 29 +++++------ docs/discovery.rst | 3 ++ .../AAA01-no-act-block-found-in-test.rst | 8 +-- ...expected-1-blank-line-before-act-block.rst | 46 ++++++++++++++--- .../AAA06-comment-in-act-block.rst | 12 ++--- docs/options.rst | 51 ++++++++++++++++++- examples/README.rst | 5 ++ 9 files changed, 131 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 505a9d7..a250feb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -28,6 +28,9 @@ See also `latest documentation provided to provide compatibility with Black versions ``23.*``. Fixes `issue 200 `_. +* 📕: New docs added for "large" Act block style. `Issue 200 + `_. + * ⛏️ Moved Black formatted test examples to their own directory. This helps when running Flake8 against Black formatted tests which need ``--aaa-act-block-style=large``. Also fix up associated Makefile recipes and diff --git a/README.rst b/README.rst index d1fbe07..d2fb874 100644 --- a/README.rst +++ b/README.rst @@ -104,7 +104,7 @@ checks provided by plugins, of which Flake8-AAA is one. Further reading: -* `Flake8's documentation `_ +* `Flake8's documentation `_. * `Awesome Flake8 Extensions `_ - a curated @@ -234,6 +234,9 @@ Flake8 with ``--select``: Further reading: +* `Flake8-AAA options and configuration + `_. + * `Using Flake8 `_. Via command line @@ -270,7 +273,8 @@ Further reading: * `Full compatibility list `_ - includes - information on support for older versions of Python. + how to configure Flake8-AAA to work with Black and information on support for + older versions of Python. 📕 Resources ------------ @@ -284,3 +288,5 @@ Further reading: * `Licensed on MIT `_ * `Changelog `_ + +* `#flake8_aaa hashtag on Mastodon `_ diff --git a/docs/compatibility.rst b/docs/compatibility.rst index 4650405..bc805e8 100644 --- a/docs/compatibility.rst +++ b/docs/compatibility.rst @@ -46,31 +46,26 @@ plugin. Yapf ---- -Yapf is used to format Flake8-AAA code and tests. It is the primary formatter -focused on for compatibility. +`Yapf `_ is used to format Flake8-AAA code and +tests. It is the primary formatter focused on for compatibility. Black ----- -Flake8-AAA is compatible with tests formatted with Black. +Flake8-AAA is compatible with tests formatted with `Black +`_. - The coding style used by Black can be viewed as a strict subset of PEP8. +Black version ``23.1.0`` changed how it managed blank lines by default. Set +:ref:`"large" Act block style option or configuration ` +when running via Flake8 for best compatibility with Black: -The AAA pattern is PEP8 compatible so it makes sense that Flake8-AAA should -work with PEP8 compatible formatters. - -This compatibility is pinned by the test examples in the `examples/good/black -directory -`_. -These tests are formatted with the latest version of Black in default mode. -They are then checked to pass Flake8-AAA's linting. +.. code-block:: shell -.. note:: + flake8 --aaa-act-block-style=large - Black version ``23.1.0`` changed how it managed blank lines by default. - This change causes Flake8-AAA to raise ``AAA03`` errors on tests that - contain context managers and are formatted with Black. See `issue #200 - `_. +See also `Black formatted example tests +`_ +in Flake8-AAA's test suite. Pytest ------ diff --git a/docs/discovery.rst b/docs/discovery.rst index a8cdaae..c4d65f7 100644 --- a/docs/discovery.rst +++ b/docs/discovery.rst @@ -116,6 +116,9 @@ There are four recognised types of Act block: Flake8-AAA searches each test function for lines that look like Act blocks. It will raise an error when a function does not have exactly 1 Act block. +The "act block style" configuration allows for a "large" style of Act block to +be specified, which changes how Act blocks are built in relation to context managers. See ... + Build Arrange and Assert blocks ............................... diff --git a/docs/error_codes/AAA01-no-act-block-found-in-test.rst b/docs/error_codes/AAA01-no-act-block-found-in-test.rst index ce3dbf4..f972c99 100644 --- a/docs/error_codes/AAA01-no-act-block-found-in-test.rst +++ b/docs/error_codes/AAA01-no-act-block-found-in-test.rst @@ -6,7 +6,7 @@ is raised. When Flake8-AAA raises ``AAA01`` it could not find an Act block in the indicated test function. Problematic code -................ +---------------- .. code-block:: python @@ -27,7 +27,7 @@ Problematic code list()[0] Correct code 1 -.............. +-------------- Use ``result =`` assignment to indicate the action in the test: @@ -55,7 +55,7 @@ Ensure all Pytest context managers are in the ``pytest`` namespace - use .. _aaa01-correct-code-2: Correct code 2 -.............. +-------------- Alternatively, mark your Act block with the ``# act`` hint to indicate the action in the test. This can be useful for scenarios where a result can not be @@ -80,7 +80,7 @@ assigned, such as tests on functions that return ``None``. list()[0] # act Rationale -......... +--------- The Act block carries out a single action on an object so it's important that Flake8-AAA can clearly distinguish which line or lines make up the Act block in diff --git a/docs/error_codes/AAA03-expected-1-blank-line-before-act-block.rst b/docs/error_codes/AAA03-expected-1-blank-line-before-act-block.rst index a50d327..7eaa1ef 100644 --- a/docs/error_codes/AAA03-expected-1-blank-line-before-act-block.rst +++ b/docs/error_codes/AAA03-expected-1-blank-line-before-act-block.rst @@ -1,17 +1,51 @@ AAA03: expected 1 blank line before Act block, found none ---------------------------------------------------------- +========================================================= For tests that have an Arrange block, there must be a blank line between the Arrange and Act blocks, but Flake8-AAA could not find one. -This blank line creates separation between the arrangement and the action and -makes the Act block easy to spot. +Prerequisites +------------- This rule works best with `pycodestyle `_'s ``E303`` rule enabled because it ensures that there are not multiple blank lines between the blocks. -Resolution -.......... +If test code is formatted with Black, then it's best to set :ref:`"large" Act +block style `. -Add a blank line before the Act block. +Problematic code +---------------- + +.. code-block:: python + + def test_simple(hello_world_path: pathlib.Path) -> None: + with open(hello_world_path) as f: + result = f.read() + + assert result == 'Hello World!\n' + +Correct code +------------ + +Since the ``open()`` context manager is part of the Arrange block, create space +between it and the ``result =`` Act block. + +.. code-block:: python + + def test_simple(hello_world_path: pathlib.Path) -> None: + with open(hello_world_path) as f: + + result = f.read() + + assert result == 'Hello World!\n' + +Alternatively, if you want the context manager to be treated as part of the Act +block, the :ref:`"large" Act block style ` as mentioned +above. + +Rationale +--------- + +This blank line creates separation between the test's Arrange and Act blocks +and makes the Act block easy to spot. diff --git a/docs/error_codes/AAA06-comment-in-act-block.rst b/docs/error_codes/AAA06-comment-in-act-block.rst index 37728a1..15834cf 100644 --- a/docs/error_codes/AAA06-comment-in-act-block.rst +++ b/docs/error_codes/AAA06-comment-in-act-block.rst @@ -1,8 +1,8 @@ AAA06: comment in Act block ---------------------------- +=========================== Problematic code -................ +---------------- .. code-block:: python @@ -23,7 +23,7 @@ Problematic code assert result == 2 Correct code -............ +------------ Use docstrings instead of hash-comments: @@ -61,7 +61,7 @@ Separate hash-comment line from Act block with a blank line: assert result == 2 Rationale -......... +--------- The Act block carries out a single action on an object. It is the focus of each test. Therefore any comments on this single action are really comments on the @@ -77,9 +77,9 @@ By placing these important comments in the docstring we can: are lifted to the top of the test. Exceptions -.......... +---------- -Inline comments used to pass information to linters are OK: +Directives in the form of inline comments are OK, for example: * Marking the Act block: diff --git a/docs/options.rst b/docs/options.rst index 7d6984a..10ac022 100644 --- a/docs/options.rst +++ b/docs/options.rst @@ -19,7 +19,10 @@ Configuration option The Act block style option adjusts how Flake8-AAA builds the Act block from the Act node. -The allowed value is "default". +The allowed values are "default" and "large". + +Default +....... In default mode the Act block is the single Act node, best demonstrated by example: @@ -51,3 +54,49 @@ context managers other than pytest or unittest ones. In the example above, Flake8-AAA considers the ``with freeze_time()`` context manager to be in the Arrange block. It therefore expects a blank line between it and the ``result =`` Act block. + +.. _large-act-block-style: + +Large +..... + +Large style Act blocks have been provided to be compatible with Black. + +In Large mode the Act block can grow to include context managers that wrap it. +For example, referring to the test above, this would be formatted as follows +with Large Act blocks: + +.. code-block:: python + + def test_with(): + a_class = AClass() + + with freeze_time("2021-02-02 12:00:02"): + result = a_class.action('test') + + assert result == 'test' + +The ``result =`` result assignment Act block expands to include the +``freeze_time()`` context manager. In this way, the blank line that divides the +Arrange block from the Act block can be *before* the context manager - a format +which is compatible with Black. + +Note however, the context manager only joined the Act block because the Act +node was the **first** line in the context manager's body. If we moved the +``AClass()`` initialisation inside the context manager, something different +would happen: + +.. code-block:: python + + def test_with(): + with freeze_time("2021-02-02 12:00:02"): + a_class = AClass() + + result = a_class.action('test') + + assert result == 'test' + +This time the result assignment does *not* consume the context manager. +Instead, the ``freeze_time()`` context manager and the ``a_class`` +initialisation make up the Arrange block, and there's a single blank line +between that and the simple result assignment Act block. diff --git a/examples/README.rst b/examples/README.rst index a97b4da..6c8a469 100644 --- a/examples/README.rst +++ b/examples/README.rst @@ -22,6 +22,11 @@ Layout Black formatted examples ------------------------ +The example tests in ``examples/black`` are copies of the ``examples/good`` +tests which are then formatted with the latest version of Black in default +mode. They are then linted with Flake8-AAA using Large-style Act blocks so that +Black's formatting of context managers passes lint. + To update the examples formatted with Black in ``examples/black`` (run from project root)::