Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[INFRA] Python test automation #44

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/run_demos_python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Python demos

# Uses the cron schedule for github actions
#
# will run at 00H00 run on the 1 and 15 of every month
#
# https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#scheduled-events
#
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC): * means all
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT): * means all
# │ │ │ │ │
# │ │ │ │ │
# │ │ │ │ │
#
# - cron "0 0 1,15 * *"

on:
schedule:
- cron: "0 0 1,15 * *"

jobs:
demos:
continue-on-error: true
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
python-version: ["3.9"]

steps:
- name: Shallow clone GLMsingle
uses: actions/checkout@v3
with:
submodules: "recursive"
fetch-depth: 0

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools
pip install .
pip install -r requirements_dev.txt

- name: Display Python version and packages
run: |
python -c "import sys; print(sys.version)"
pip list

- name: Run notebooks
run: pytest --nbmake --nbmake-timeout=3000 "./examples"
54 changes: 54 additions & 0 deletions .github/workflows/run_tests_python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Python tests

on:
push:
branches: ["main"]
pull_request:
branches: ["*"]

jobs:
tests:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
python-version: ["3.7", "3.8", "3.9"] # fails on 3.10
fail-fast: true # cancel all jobs if one fails

steps:
- name: Shallow clone GLMsingle
uses: actions/checkout@v3
with:
submodules: "recursive"
fetch-depth: 0

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools
pip install .
pip install -r requirements_dev.txt

- name: Display Python version and packages
run: |
python -c "import sys; print(sys.version)"
pip list

- name: Prepare data
run: make tests/data/nsdcoreexampledataset.mat

- name: Run tests and generate coverage report
run: pytest -v --cov glmsingle --cov-report xml tests

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
file: ./coverage.xml
flags: python
name: codecov-umbrella
fail_ci_if_error: true
verbose: true
11 changes: 8 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#
# vscode files
.vscode/

# test related
tests/outputs/

# data folder
# data folders
data/

# example output folders
Expand All @@ -13,6 +15,9 @@ figures/
report.html
##*.png

# pyenv
Pipfile

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down Expand Up @@ -54,6 +59,7 @@ pip-delete-this-directory.txt
htmlcov/
.tox/
.coverage
coverage_html
.coverage.*
.cache
nosetests.xml
Expand Down Expand Up @@ -153,4 +159,3 @@ codegen/

# Octave session info
octave-workspace

7 changes: 7 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
hooks:
- id: check-yaml
108 changes: 108 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# CONTRIBUTING

Information for anyone who would like to contribute to this repository.

## Repository map

```bash
├── .git
├── .github
│ └── workflows # Github continuous integration set up
├── examples # Python demos: jupyter notebooks
│ ├── data
│ ├── example1outputs
│ ├── example2outputs
├── glmsingle # Python implementation
│ ├── cod
│ ├── design
│ ├── gmm
│ ├── hrf
│ ├── ols
│ ├── ssq
│ └── utils
├── matlab # MATLAB implementation
│ ├── examples # MATLAB demos
│ ├── fracridge
│ └── utilities
└── tests # Python and MATLAB tests
└── data

```

## Generic

### Makefile

### pre-commit

## Matlab

### Style guide

### Tests

#### Demos

### Continuous integration

## Python

All the packages required to help with the python development of GLMsingle can
be installed with:

```bash
pip install -r requirements_dev.txt
```

### Style guide

[black](https://black.readthedocs.io/en/stable/) (code formater) and
[flake8](https://flake8.pycqa.org/en/latest/) (style guide enforcement) are used
on the test code base.

Ypu can use make to run them automatically with

```bash
make lint/black # to run black
make lint/flake8 # to run flake8
make lint # to run both
```
Comment on lines +59 to +69
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of those are for code styling, so it does not have to be done manually. Only applies to the test code base.

Can remove it if you want.


### Tests

The tests can be run with with pytest via the make command:

```bash
make test-python
```

#### Demos

The jupyter notebook are tested with the
[`nbmake` plugin for pytest](https://pypi.org/project/nbmake/).

They can be run with the make command:

```bash
make test-notebooks
```

### Continuous integration

We use Github to run several workflows for continuous integration.

#### Tests

The python tests are run by the workflow:
`.github/workflows/run_tests_python.yaml`.

Those tests should be run with every push on the `master` branch and on pull
request that target the `master` branch.

#### Demos

The demos in the `examples` folder are run automatically in Github CI at regular
intervals.

The jupyter notebooks are run by the workflow
`.github/workflows/run_demos_python.yaml`.
114 changes: 114 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
.DEFAULT_GOAL := help

BROWSER := python -c "$$BROWSER_PYSCRIPT"

# TODO make more general to use the local matlab version
MATLAB = /usr/local/MATLAB/R2017a/bin/matlab
MATLAB_ARG = -nodisplay -nosplash -nodesktop

define BROWSER_PYSCRIPT
import os, webbrowser, sys

from urllib.request import pathname2url

webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1])))
endef
export BROWSER_PYSCRIPT

# determines what "make help" will show
define PRINT_HELP_PYSCRIPT
import re, sys

for line in sys.stdin:
match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line)
if match:
target, help = match.groups()
print("%-20s %s" % (target, help))
endef
export PRINT_HELP_PYSCRIPT

################################################################################
# GENERIC
.PHONY: help clean clean-test lint install_dev

help:
@python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
clean: clean-build clean-pyc clean-test ## remove all build, test, coverage artifacts

clean-test: ## remove test and coverage artifacts
rm -rf .tox/
rm -rf .coverage
rm -rf htmlcov/
rm -rf .pytest_cache
rm -rf tests/data
rm -rf test/outputs

install_dev: ## install for both matlab and python developpers
pip install -e .
pip install -r requirements_dev.txt

lint: lint/black lint/flake8 lint/miss_hit ## check style

test: test-matlab test-python

tests/data/nsdcoreexampledataset.mat:
mkdir tests/data
curl -fsSL --retry 5 -o "tests/data/nsdcoreexampledataset.mat" https://osf.io/k89b2/download

################################################################################

################################################################################
# MATLAB

.PHONY: lint/miss_hit

lint/miss_hit: ## lint and checks matlab code
mh_style --fix tests && mh_metric --ci tests && mh_lint tests

test-matlab: tests/data/nsdcoreexampledataset.mat
$(MATLAB) $(MATLAB_ARG) -r "run_tests; exit()"

coverage-matlab: test-matlab
$(BROWSER) coverage_html/index.html

################################################################################

################################################################################
# PYTHON

.PHONY: clean-build clean-pyc coverage-python install lint/flake8 lint/black

clean-build: ## remove build artifacts
rm -fr build/
rm -fr dist/
rm -fr .eggs/
find . -name '*.egg-info' -exec rm -fr {} +
find . -name '*.egg' -exec rm -f {} +

clean-pyc: ## remove Python file artifacts
find . -name '*.pyc' -exec rm -f {} +
find . -name '*.pyo' -exec rm -f {} +
find . -name '*~' -exec rm -f {} +
find . -name '__pycache__' -exec rm -fr {} +

lint/flake8: ## check style with flake8
flake8 tests
lint/black: ## check style with black
black tests

test-python: tests/data/nsdcoreexampledataset.mat ## run tests quickly with the default Python
pytest -vv

test-notebooks:
pytest -vv --nbmake --nbmake-timeout=3000 "./examples"
test-all: ## run tests on every Python version with tox
tox

coverage-python: ## check code coverage quickly with the default Python
pytest -vv --cov glmsingle --cov-report html:htmlcov
$(BROWSER) htmlcov/index.html

install: clean ## install the package to the active Python's site-packages
python setup.py install

################################################################################
Loading