diff --git a/.gitignore b/.gitignore
index 67eac53b45cd59a8db7b5e988128fb80bece7faf..7e8ebcd581704b17425f5a7576c1ae3c139f59dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,5 @@ dist/*
 *.pyc
 
 .coverage
+coverage.xml
+htmlcov/*
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5788612ec2ee35c80bbd59e80dcc9e3daef340cc..b17457db642b7eceb4eed0f04724adb973ba7f4e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -45,6 +45,19 @@ run_pylint:
 #   script:
 #     - echo "build fortran/c/cpp extension source code"
 
+run_unit_tests_coverage:
+  stage: test
+  image: python:3.7
+  script:
+   - tox -e coverage
+  artifacts:
+    reports:
+      coverage_report:
+        coverage_format: cobertura
+        path: coverage.xml
+    paths:
+      - htmlcov/*
+
 run_unit_tests:
   stage: test
   image: python:3.${PY_VERSION}
diff --git a/README.md b/README.md
index 605e1f0c43569ad5546b1bcaa6247a6fb5074475..979ee10941a6ed6da6e3617a93241d1d32c8cc6e 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,22 @@ cool_module.greeter()   # prints "Hello World"
 ## Contributing
 
 To contribute, please create a feature branch and a "Draft" merge request.
-Upon completion, the merge request should be marked as ready and a reviewer should be assigned.
+Upon completion, the merge request should be marked as ready and a reviewer
+should be assigned.
+
+Verify your changes locally and be sure to add tests. Verifying local
+changes is done through `tox`.
+
+```pip install tox```
+
+With tox the same jobs as run on the CI/CD pipeline can be ran. These
+include unit tests and linting.
+
+```tox```
+
+To automatically apply most suggested linting changes execute:
+
+```tox -e format```
 
 ## License
 This project is licensed under the Apache License Version 2.0
diff --git a/tests/requirements.txt b/tests/requirements.txt
index ada64140f70e847fe9bc4e95f51aebc9e326a9e5..f14d0b907ce977320ba250046dfab52a3101800a 100644
--- a/tests/requirements.txt
+++ b/tests/requirements.txt
@@ -1,3 +1,4 @@
+autopep8 >= 1.7.0 # MIT
 black >= 22.0.0 # MIT
 build >= 0.8.0 # MIT
 flake8 >= 5.0.0 # MIT
diff --git a/tox.ini b/tox.ini
index 0c73407b467025c899dbf77bd869e9633a6f0356..c0530645e8f647ea7d94921271c1227dcd3522b0 100644
--- a/tox.ini
+++ b/tox.ini
@@ -16,11 +16,16 @@ deps =
     -r{toxinidir}/tests/requirements.txt
 commands =
     {envpython} --version
-    {envpython} -m pytest --cov=map
+    {envpython} -m pytest
+
+[testenv:coverage]
+commands =
+    {envpython} --version
+    {envpython} -m pytest --cov-report xml --cov-report html --cov=map
 
 # Use generative name and command prefixes to reuse the same virtualenv
 # for all linting jobs.
-[testenv:{pep8,black,pylint}]
+[testenv:{pep8,black,pylint,format}]
 usedevelop = False
 envdir = {toxworkdir}/linting
 commands =
@@ -30,6 +35,10 @@ commands =
     black: {envpython} -m black --check --diff .
     pylint: {envpython} -m pylint --version
     pylint: {envpython} -m pylint map tests
+    format: {envpython} -m autopep8 -v -aa --in-place --recursive map
+    format: {envpython} -m autopep8 -v -aa --in-place --recursive tests
+    format: {envpython} -m black -v .
+
 
 [testenv:build]
 usedevelop = False