Repository: eecs485staff/madoop (language: python)

Issue:
Tests
Tweaks to the unit and system tests

## Validation
```console
$ git clean -xdf
$ python3 -m venv .venv
$ source env/bin/activate
$ pip install -e .
$ pylint madoop tests/* setup.py
$ pycodestyle madoop tests setup.py
$ pydocstyle madoop tests setup.py
$ pytest -vvsx
```

Closes #6
CI Regression Tests
Run regression tests using GitHub Actions CI

## TODO
- [ ] Tox config
- [ ] Run tests against different Python versions
- [ ] Style checks
- [ ] Coverage checks


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml
new file mode 100644
index 0000000..4ed941a
--- /dev/null
+++ b/.github/workflows/continuous_integration.yml
@@ -0,0 +1,60 @@
+# GitHub Continuous Integration Configuration
+name: CI
+
+# Define conditions for when to run this action
+on:
+  pull_request: # Run on all pull requests
+  push: # Run on all pushes to master
+    branches:
+      - main
+      - develop
+
+  # Allows you to run this workflow manually from the Actions tab
+  workflow_dispatch:
+
+# A workflow run is made up of one or more jobs.  Each job has an id, for
+# example, one of our jobs is "lint"
+jobs:
+  test:
+    name: Tests ${{ matrix.python-version }}
+    runs-on: ${{ matrix.os }}
+    strategy:
+      # Define OS and Python versions to use. 3.x is the latest minor version.
+      matrix:
+        python-version: ["3.6", "3.x"]  # 3.x is the latest minor version
+        os: [ubuntu-latest]
+
+    # Sequence of tasks for this job
+    steps:
+      # Check out latest code
+      # Docs: https://github.com/actions/checkout
+      - name: Checkout code
+        uses: actions/checkout@v2
+
+      # Set up Python
+      # Docs: https://github.com/actions/setup-python
+      - name: Set up Python ${{ matrix.python-version }}
+        uses: actions/setup-python@v2
+        with:
+          python-version: ${{ matrix.python-version }}
+
+      # Install dependencies
+      # https://github.com/ymyzk/tox-gh-actions#workflow-configuration
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          pip install coverage tox tox-gh-actions
+
+      # Run tests
+      # https://github.com/ymyzk/tox-gh-actions#workflow-configuration
+      - name: Run tests
+        run: tox
+      # - name: Combine coverage
+      #   run: coverage xml
+
+      # Upload coverage report
+      # https://github.com/codecov/codecov-action
+      # - name: Upload coverage report
+      #   uses: codecov/codecov-action@v1
+      #   with:
+      #     fail_ci_if_error: true
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..689df6e
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,13 @@
+include LICENSE
+include MANIFEST.in
+include README.md
+include CONTRIBUTING.md
+include .pylintrc
+graft tests
+include test
+
+# Avoid dev and and binary files
+exclude tox.ini
+exclude .editorconfig
+global-exclude *.pyc
+global-exclude __pycache__
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..e0a9bc9
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,27 @@
+# Local host configuration with one Python 3 version
+[tox]
+envlist = py36, py37, py38, py39, py310
+
+# GitHub Actions configuration with multiple Python versions
+# https://github.com/ymyzk/tox-gh-actions#tox-gh-actions-configuration
+[gh-actions]
+python =
+  3.6: py36
+  3.7: py37
+  3.8: py38
+  3.9: py39
+  3.10: py310
+
+# Run unit tests
+# HACK: Pydocstyle fails to find tests.  Invoke a shell to use a glob.
+[testenv]
+setenv =
+  PYTHONPATH = {toxinidir}
+allowlist_externals = sh
+extras = dev
+commands =
+  pycodestyle madoop tests setup.py
+  sh -c "pydocstyle madoop tests/* setup.py"
+  pylint madoop tests setup.py
+  check-manifest
+  pytest -vvs


Test patch:
diff --git a/tests/test_stages.py b/tests/test_stages.py
index 15869be..8f49385 100644
--- a/tests/test_stages.py
+++ b/tests/test_stages.py
@@ -1,6 +1,4 @@
-"""
-System tests for the map stage of Michigan Hadoop.
-"""
+"""System tests for the map stage of Michigan Hadoop."""
 import pathlib
 import filecmp
 import madoop
@@ -11,7 +9,7 @@
 
 
 def test_map_stage(tmpdir):
-    """Test the map stage using word count example"""
+    """Test the map stage using word count example."""
     madoop.__main__.map_stage(
         exe=TESTDATA_DIR/"word_count/map.py",
         input_dir=TESTDATA_DIR/"word_count/correct/hadooptmp/mapper-input",
@@ -27,7 +25,7 @@ def test_map_stage(tmpdir):
 
 
 def test_group_stage(tmpdir):
-    """Test group stage using word count example"""
+    """Test group stage using word count example."""
     madoop.__main__.group_stage(
         input_dir=TESTDATA_DIR/"word_count/correct/hadooptmp/mapper-output",
         output_dir=tmpdir,
@@ -40,7 +38,7 @@ def test_group_stage(tmpdir):
 
 
 def test_reduce_stage(tmpdir):
-    """Test reduce stage using word count example"""
+    """Test reduce stage using word count example."""
     madoop.__main__.reduce_stage(
         exe=TESTDATA_DIR/"word_count/reduce.py",
         input_dir=TESTDATA_DIR/"word_count/correct/hadooptmp/grouper-output",