PyNose
A test smell detector for Python.
Install / Use
/learn @JetBrains-Research/PyNoseREADME
PyNose: a Test Smell Detector for Python
PyNose is a test smell detector tool for Python. It runs as a plugin inside the PyCharm IDE (version 2021.3)
Note: PyNose is currently under active development, the older version of the tool that was initially described in the paper "PyNose: A Test Smell Detector For Python" can be found in the ASE2021 branch.
How to use in PyCharm
- Download the latest release of the plugin from here;
- Open PyCharm and go to
File/Settings/Plugins; - Select the gear icon, and choose
Install Plugin from Disk...; - Choose the downloaded ZIP archive;
- Click
Apply; - Restart the IDE.
Description
PyNose can be used inside the IDE to study the test smells within a specific opened project. This can help python developers avoid test smells in their code.
When you open a project in PyCharm, a number of inspections will be available for usage.
PyNose will retrieve the information about your currently configured Test Runner (Preferences > Tools > Python Integrated Tools > Testing > Default test runner) to use the appropriate set of inspections (pytest or Unittest).
Some inspections are initially disabled, however you can enable them from the settings.
Available inspections
| Inspections |Unittest|Pytest |Quick fix |Warning level|Description| | ------------- |:------:|:-----:|:--------------------------------------:|:-----------:|:----------| |Assertion Roulette |+ |+ |- |Disabled* | A test case contains more than one assertion statement without an explanation| |Conditional Test Logic |+ |+ |- |Disabled | Presence of control statements (i.e., if, for, while)| |Constructor Initialization |+ |- |+ (move logic to setup) |Weak warning | A test suite contains a constructor declaration (an __init__ method)| |Default Test |+ |- |+ (suggest rename refactoring) |Weak warning | A test suite is called MyTestCase| |Duplicate Assert |+ |+ |+ (remove duplicate) |Warning | Occurrence of more than one assertion statement with the same parameters| |Empty Test |+ |+ |+ (safe delete) |Warning | A test case does not contain a single executable statement| |Exception Handling |+ |+ |+ (replace with framework raise handler)|Warning | Presence of either the try/except statement or the raise statement| |Lack of Cohesion of Test Cases |+ |+ |- |Disabled | Test suites in a test case are not cohesive according to pairwise cosine similarities metric| |Magic Number Test |+ |+ |- |Disabled | Presence of an assertion statement with a numeric literal as an argument| |Obscure In-Line Setup |+ |+ |- |Disabled | A test case contains ten or more local variables declarations| |Redundant Assertion |+ |+ |+ (remove assertion) |Warning | Presence of assertions the result of which never changes (i.e., assert 1 == 1)| |Redundant Print |+ |+ |+ (remove statement) |Disabled | print() function invocation| |Sleepy Test |+ |+ |+ (remove statement) |Disabled | time.sleep() function invocation| |Suboptimal Assert |+ |- |+ (replace with optimal) |Warning | Presence of one of the suboptimal asserts**| |Test Maverick |+ |+ |- |Disabled | A test suite contains at least one test case that does not use a single field from the setup method|
*Disabled by default. If enabled — weak warning.
**List of suboptimal assertions is available here.
Usage examples
-
Suboptimal assertion detection and quick fix <br></br>
<br></br> -
Exception handling detection and quick fix <br></br>
<br></br>
Contacts
If you have any questions or suggestions, don't hesitate to open an issue or contact Yaroslav Golubev at yaroslav.golubev@jetbrains.com.
