<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Madelyn Eriksen</title>
    <description>The latest articles on DEV Community by Madelyn Eriksen (@madelyneriksen).</description>
    <link>https://dev.to/madelyneriksen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F188064%2F40302d20-52f6-4c6e-8f78-241a1eda83b4.jpeg</url>
      <title>DEV Community: Madelyn Eriksen</title>
      <link>https://dev.to/madelyneriksen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/madelyneriksen"/>
    <language>en</language>
    <item>
      <title>5 Awesome Tools For Python Code Quality</title>
      <dc:creator>Madelyn Eriksen</dc:creator>
      <pubDate>Sun, 30 Jun 2019 00:08:51 +0000</pubDate>
      <link>https://dev.to/madelyneriksen/5-awesome-tools-for-python-code-quality-2pc</link>
      <guid>https://dev.to/madelyneriksen/5-awesome-tools-for-python-code-quality-2pc</guid>
      <description>&lt;p&gt;&lt;em&gt;Alternate Title: A developer adds five lines to her &lt;code&gt;.travis.yml&lt;/code&gt; file. You won't believe what happens next!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Code quality is critical to keeping large projects healthy and progressing, but it's hard to maintain consistent quality by hand. However, there are a bunch of tools for Python code that will make this so much easier.&lt;/p&gt;

&lt;p&gt;Like several other topics in software development, what tools to use comes down to preference. Do you use a tool not on this list? Feel free to let me know what I am missing! What follows is my personal preference in tools as of 2019.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Pytest - Essential Unit Testing
&lt;/h2&gt;

&lt;p&gt;Python has a built in unit testing toolkit in the &lt;code&gt;unittest&lt;/code&gt; module, but it's not always the right fit for every project. I prefer using &lt;a href="https://pytest.org"&gt;Pytest&lt;/a&gt; whenever possible because the experience is so simple.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It's Good&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When it's easier to write unit tests, you'll write more of them. Pytest makes it a &lt;em&gt;breeze&lt;/em&gt; to create new tests. Just add a new Python file that starts with &lt;code&gt;test&lt;/code&gt;, write a few functions, and you're already done.&lt;/p&gt;

&lt;p&gt;There are a massive amount of plugins for Pytest that can be configured through a &lt;code&gt;pytest.ini&lt;/code&gt; file. It's also easy and painless to write your own plugins too! And of course, Pytest "just works" with class based tests from &lt;code&gt;unittest&lt;/code&gt;, too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How To Use It&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Say you were writing a test to see if addition works, and in this alternate universe it also didn't bother you this exercise seemed so contrived. You might write a pytest file like this in a &lt;code&gt;tests&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="s"&gt;"""An Example Pytest Test"""&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pytest&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_plus_one&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s"&gt;"""Test some addition."""&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;integration&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow_test&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s"&gt;"""A really slow integration test."""&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You would also write up a &lt;code&gt;pytest.ini&lt;/code&gt; file to register the "slow" marker, otherwise you will get an unpleasant warning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[pytest]&lt;/span&gt;
&lt;span class="py"&gt;markers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="err"&gt;integration:&lt;/span&gt; &lt;span class="err"&gt;Integration&lt;/span&gt; &lt;span class="err"&gt;test.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And... that's it. That's all it takes to create new Pytest tests. You can run them by installing Pytest from PyPi and running the &lt;code&gt;pytest&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;pytest
pytest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It's that easy. 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Pylint - Style Checking and Error Spotting
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.pylint.org/"&gt;Pylint&lt;/a&gt; is an &lt;em&gt;intelligent&lt;/em&gt; code analysis tool that understands your Python code. It catches common errors like misspelled variable names, to sneakier problems like non-returning branches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It's Good&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unlike a lot of other tools for linting Python code, Pylint can spot some logical errors or code that will result in exceptions. It also enforces a lot of best practices, such as keeping &lt;code&gt;try ... except&lt;/code&gt; blocks focused on a few &lt;em&gt;specific&lt;/em&gt; exception classes, and avoiding bad default arguments like empty lists or dictionaries.&lt;/p&gt;

&lt;p&gt;Pylint is unrivaled in strictness- it has a &lt;em&gt;lot&lt;/em&gt; of checks for everything from superfluous warnings to serious errors. The downside to using Pylint is sometimes the check is just wrong; you'll want to keep your &lt;code&gt;.pylintrc&lt;/code&gt; file close when you know you're right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to Use It&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Like most Python tools, you can download Pylint from PyPi using &lt;code&gt;pip&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;pylint
&lt;span class="c"&gt;# Lint your project with the module (folder) name&lt;/span&gt;
pylint my_project
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You might want to also create a &lt;code&gt;.pylintrc&lt;/code&gt; file for your project. This file should be checked into source control, as well. Pylint can generate a default &lt;code&gt;.pylintrc&lt;/code&gt; file for you, too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pylint &lt;span class="nt"&gt;--generate-rcfile&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .pylintrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There are also plugins to integrate Pylint with Pytest, if you don't feel like using a task runner or builder like &lt;a href="https://www.madelyneriksen.com/blog/gnu-make-for-beginners"&gt;GNU Make&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Black - Code Formatting for Python
&lt;/h2&gt;

&lt;p&gt;Why spend energy beautifying your code, when you can outsource the work to a computer? &lt;a href="https://github.com/python/black"&gt;Black&lt;/a&gt; is a code formatter for Python that's fast and 100% static- it doesn't import code to format it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It's Good&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Personally, while I love clean and pretty Python code, it is &lt;strong&gt;exhausting&lt;/strong&gt; to format code by hand. It's so much easier to just throw lines into a source file without worrying about line wrapping, indentation, or long function signatures.&lt;/p&gt;

&lt;p&gt;Black takes away all this responsibility from the programmer, instead formatting the code itself. It's fast and efficient with defaults that reduce "diff" sizes. I have no complaints about Black- I love it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How To Use It&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just install Black from PyPi and format your files. You're good to go! 🚀&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;black
&lt;span class="c"&gt;# Format everything in my_project/&lt;/span&gt;
black my_project
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For CI/CD pipelines, you might want to check that all code is formatted with Black. That's what the check option is for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;black my_project &lt;span class="nt"&gt;--check&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--check&lt;/code&gt; will fail the tests if the code isn't all formatted already.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Coverage - Easy Code Coverage for Python
&lt;/h2&gt;

&lt;p&gt;If you're going to the trouble of writing unit tests, you might as well check if you missed a spot. &lt;a href="https://coverage.readthedocs.io/"&gt;Coverage&lt;/a&gt; is an easy way to check code coverage using almost any existing tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It's Good&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Test coverage, while not a silver bullet, is a great way to maintain a quality code base. It becomes easy to see what the weakest test areas in the project are- just check the reports!&lt;/p&gt;

&lt;p&gt;When you are writing new features, a lackluster coverage report can help nudge you in the right direction. I find having a target number helps a lot with my motivation to test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How To Use It&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Like everything else on this list, Coverage is installed from PyPy using &lt;code&gt;pip&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;coverage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To measure coverage of your source code, pass in the directory to &lt;code&gt;coverage run&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# With Pytest&lt;/span&gt;
coverage run &lt;span class="nt"&gt;--source&lt;/span&gt; my_project pytest
&lt;span class="c"&gt;# View the reports!&lt;/span&gt;
coverage report
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There's also a great &lt;a href="https://pypi.org/project/pytest-cov/"&gt;plugin&lt;/a&gt; for Pytest that will run &lt;code&gt;coverage&lt;/code&gt; alongside Pytest. This is great because you can see the coverage numbers every test. 😎&lt;/p&gt;

&lt;h2&gt;
  
  
  5. MyPy - Type Checking for Python
&lt;/h2&gt;

&lt;p&gt;This is a relatively new addition to my list, but so far I like &lt;a href="http://mypy-lang.org/"&gt;MyPy&lt;/a&gt; for typechecking Python. Sometimes there are "gotchyas" if your code (ab)uses the dynamic features of Python, but for the most part it gets things right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It's Good&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Having good unit test coverage can prevent a lot of &lt;code&gt;TypeErrors&lt;/code&gt;, but MyPy can augment a good test suite by double checking how you use your types. Type annotations in Python also serve as a form of documentation, showcasing what &lt;strong&gt;exactly&lt;/strong&gt; each function and class expects.&lt;/p&gt;

&lt;p&gt;The only downside to MyPy is mostly the fact that Python is a dynamic language: MyPy needs types to be defined in external modules if you want to check how you use their code too, plus it doesn't handle things like dynamic class creation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How To Use It&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MyPy is also easy to use. You should create a &lt;code&gt;mypy.ini&lt;/code&gt; file, plus install it from PyPi.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;mypy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Run MyPy against your source code directory using the &lt;code&gt;mypy&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;mypy my_project
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you don't see anything (and the exit code is zero 😉), congrats- it's working just fine, and your code passed!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Code quality in big projects can be a serious pain, but in a lot of areas our tools can help out. Drop a few of these tools into you CI/CD pipeline, it's easy to get started! A great CI/CD pipeline can save a lot (A LOT) of headache down the road.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PSST:&lt;/strong&gt; I created a &lt;a href="https://github.com/madelyneriksen/cookiecutter-python-goodstuff/"&gt;cookiecutter&lt;/a&gt; that shows an example of how I integrate all these into my projects. If you are interested, check it out!&lt;/p&gt;

&lt;p&gt;See you around! Cheers.&lt;/p&gt;

</description>
      <category>python</category>
      <category>codequality</category>
    </item>
  </channel>
</rss>
