Skip to content

Separate static analysis, move tests out of the package #1528

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

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
31 changes: 19 additions & 12 deletions .azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,32 @@ jobs:
- script: |
python -m pip install --upgrade pip
pip install pytest-azurepipelines wheel
pip install -e .[dev,doc,test,louvain,leiden,magic,scvi,harmony]
pip install .[dev,doc,test,louvain,leiden,magic,scvi,harmony]
displayName: 'Install dependencies'

- script: |
pip install -v git+https://github.com/theislab/anndata
- script: pip install -v git+https://github.com/theislab/anndata
displayName: 'Install development anndata'
condition: eq(variables['ANNDATA_DEV'], 'yes')

- script: pytest --ignore=tests/_images
displayName: 'PyTest'

- job: static_analysis
pool:
vmImage: 'ubuntu-16.04'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.8'
displayName: 'Use Python 3.8'

- script: pip install black docutils
displayName: 'Install dependencies'
Comment on lines +41 to +51
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure this should be a separate job. I would prefer we use the jobs we have for other operating systems. Azure allows us to have multiple checks within a job, so I'm not sure it's that useful to put static analysis in it's own build.

Copy link
Member Author

Choose a reason for hiding this comment

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

that way it runs much faster, so people see earlier if they didn’t format things properly


- script: |
pip install black
black . --check --diff
python -m scanpy.tests.blackdiff 10
python -m tests.blackdiff 10
displayName: 'Black'

- script: |
pytest --ignore=scanpy/tests/_images
displayName: 'PyTest'

- script: |
python setup.py check --restructuredtext --strict
rst2html.py --halt=2 README.rst >/dev/null
- script: rst2html.py --halt=2 README.rst >/dev/null
displayName: 'rst2html'
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ matrix:
- pip install .[dev,doc]
script:
- black . --check --diff
- python -m scanpy.tests.blackdiff 10
- python -m tests.blackdiff 10
- python setup.py check --restructuredtext --strict
- rst2html.py --halt=2 README.rst >/dev/null
after_success: skip
Expand All @@ -33,4 +33,4 @@ install:
env:
- MPLBACKEND=Agg
script:
- pytest --ignore=scanpy/tests/_images
- pytest --ignore=tests/_images
14 changes: 1 addition & 13 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ author-email = '[email protected], [email protected]'

[tool.pytest.ini_options]
python_files = 'test_*.py'
testpaths = 'scanpy/tests/'
testpaths = 'tests/'
xfail_strict = true
markers = [
'internet: tests which rely on internet resources (enable with `--internet-tests`)',
Expand Down Expand Up @@ -60,16 +60,4 @@ exclude = '''
|palettes
|_tools/(__init__|paga)
)
|tests/(
test_get
|test_neighbors
|test_readwrite
|test_clustering
|test_preprocessing
|test_rank_genes_groups
|test_marker_gene_overlap
|test_highly_variable_genes
|test_rank_genes_groups_logreg
|notebooks/(test_paga_paul15_subsampled|test_pbmc3k)
)
).py'''
47 changes: 0 additions & 47 deletions scanpy/tests/conftest.py

This file was deleted.

23 changes: 0 additions & 23 deletions scanpy/tests/fixtures.py

This file was deleted.

69 changes: 0 additions & 69 deletions scanpy/tests/helpers.py

This file was deleted.

17 changes: 0 additions & 17 deletions scanpy/tests/test_readwrite.py

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
140 changes: 140 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import sys
from pathlib import Path

import matplotlib as mpl
import numpy as np
from anndata import AnnData
from scipy import sparse
from anndata.tests.helpers import asarray, assert_equal

mpl.use('agg')
from matplotlib import pyplot
from matplotlib.testing.compare import compare_images
import pytest

import scanpy

scanpy.settings.verbosity = "hint"

# define this after importing scanpy but before running tests
IMPORTED = frozenset(sys.modules.keys())


@pytest.fixture
def imported_modules():
return IMPORTED


def make_comparer(path_expected: Path, path_actual: Path, *, tol: int):
def save_and_compare(basename, tolerance=None):
path_actual.mkdir(parents=True, exist_ok=True)
out_path = path_actual / f'{basename}.png'
pyplot.savefig(out_path, dpi=40)
pyplot.close()
if tolerance is None:
tolerance = tol
res = compare_images(
str(path_expected / f'{basename}.png'), str(out_path), tolerance
)
assert res is None, res

return save_and_compare


@pytest.fixture
def image_comparer():
return make_comparer


@pytest.fixture
def plt():
return pyplot


@pytest.fixture(
params=[sparse.csr_matrix, sparse.csc_matrix, asarray],
ids=["scipy-csr", "scipy-csc", "np-ndarray"],
)
def array_type(request):
"""Function which converts passed array to one of the common array types."""
return request.param


@pytest.fixture(params=[np.float64, np.float32])
def float_dtype(request):
return request.param


###########################
# Representation choice
###########################
# These functions can be used to check that functions are correctly using arugments
# like `layers`, `obsm`, etc.


@pytest.fixture(scope='session')
def check_rep_mutation():
def check_rep_mutation(func, X, **kwargs):
"""Check that only the array meant to be modified is modified."""
adata = AnnData(
X=X.copy(),
layers={"layer": X.copy()},
obsm={"obsm": X.copy()},
dtype=X.dtype,
)
adata_X = func(adata, copy=True, **kwargs)
adata_layer = func(adata, layer="layer", copy=True, **kwargs)
adata_obsm = func(adata, obsm="obsm", copy=True, **kwargs)

assert np.array_equal(asarray(adata_X.X), asarray(adata_layer.layers["layer"]))
assert np.array_equal(asarray(adata_X.X), asarray(adata_obsm.obsm["obsm"]))

assert np.array_equal(asarray(adata_layer.X), asarray(adata_layer.obsm["obsm"]))
assert np.array_equal(
asarray(adata_obsm.X), asarray(adata_obsm.layers["layer"])
)
assert np.array_equal(
asarray(adata_X.layers["layer"]), asarray(adata_X.obsm["obsm"])
)

return check_rep_mutation


@pytest.fixture(scope='session')
def check_rep_results():
def check_rep_results(func, X, **kwargs):
"""Checks that the results of a computation add values/
mutate the anndata object in a consistent way.
"""
# Gen data
adata_X = AnnData(
X=X.copy(),
layers={"layer": np.zeros(shape=X.shape, dtype=X.dtype)},
obsm={"obsm": np.zeros(shape=X.shape, dtype=X.dtype)},
)
adata_layer = AnnData(
X=np.zeros(shape=X.shape, dtype=X.dtype),
layers={"layer": X.copy()},
obsm={"obsm": np.zeros(shape=X.shape, dtype=X.dtype)},
)
adata_obsm = AnnData(
X=np.zeros(shape=X.shape, dtype=X.dtype),
layers={"layer": np.zeros(shape=X.shape, dtype=X.dtype)},
obsm={"obsm": X.copy()},
)

# Apply function
func(adata_X, **kwargs)
func(adata_layer, layer="layer", **kwargs)
func(adata_obsm, obsm="obsm", **kwargs)

# Reset X
adata_X.X = np.zeros(shape=X.shape, dtype=X.dtype)
adata_layer.layers["layer"] = np.zeros(shape=X.shape, dtype=X.dtype)
adata_obsm.obsm["obsm"] = np.zeros(shape=X.shape, dtype=X.dtype)

# Check equality
assert_equal(adata_X, adata_layer)
assert_equal(adata_X, adata_obsm)

return check_rep_results
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading