Skip to content

Commit

Permalink
Merge pull request #393 from ral-facilities/tests/reorganise-tests#375
Browse files Browse the repository at this point in the history
Tests/reorganise tests#375
  • Loading branch information
Reillyhewitson authored Feb 6, 2023
2 parents 71d81ac + 619d3e4 commit b08022a
Show file tree
Hide file tree
Showing 86 changed files with 473 additions and 243 deletions.
66 changes: 46 additions & 20 deletions .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,48 @@ jobs:
python-version: ${{ matrix.python-version }}
architecture: x64

- name: Checkout DataGateway API
uses: actions/checkout@v2

# Install Nox, Poetry and API's dependencies
- name: Install Nox
run: pip install nox==2020.8.22
- name: Install Poetry
run: pip install poetry==1.1.9

# This command is a workaround for getting Poetry working with Python 3.10. An
# fix is made in Poetry 1.2.0a2 but there is currently no official release for
# Poetry 1.2 and am apprehensive to moving to a pre-release. Disabling the
# experimental installer is a workaround for Poetry 1.1.x
# See https://github.com/python-poetry/poetry/issues/4210 for more details
- name: Disable Poetry's experimental new installer
if: ${{ matrix.python-version == '3.10' }}
run: poetry config experimental.new-installer false

# Prep for using the API for tests
- name: Create log file
run: touch logs.log
- name: Configure log file location
run: echo "`yq \
'.log_location="${GITHUB_WORKSPACE}/logs.log"' datagateway_api/config.yaml.example | envsubst`" > datagateway_api/config.yaml.example
- name: Configure datagateway extension
run: echo "`yq \
'.datagateway_api.extension="/datagateway_api"' datagateway_api/config.yaml.example`" > datagateway_api/config.yaml.example
- name: Create config.yaml
run: cp datagateway_api/config.yaml.example datagateway_api/config.yaml
- name: Create search_api_mapping.json
run: cp datagateway_api/search_api_mapping.json.example datagateway_api/search_api_mapping.json

# Run Unit tests
- name: Run Nox unit tests session
run: nox -p ${{ matrix.python-version }} -s unit_tests -- --cov=datagateway_api --cov-report=xml
- name: Upload unit test code coverage report
if: matrix.python-version == '3.6'
uses: codecov/codecov-action@v3

# ICAT Ansible clone and install dependencies
- name: Checkout icat-ansible
if: success()
uses: actions/checkout@v2
with:
repository: icatproject-contrib/icat-ansible
Expand Down Expand Up @@ -94,39 +134,25 @@ jobs:
- name: Create search_api_mapping.json
run: cp datagateway_api/search_api_mapping.json.example datagateway_api/search_api_mapping.json

# Install Nox, Poetry and API's dependencies
- name: Install Nox
run: pip install nox==2020.8.22
- name: Install Poetry
run: pip install poetry==1.1.9

# Installing an older version of setuptools for reasons explained at: https://github.com/icatproject/python-icat/issues/99
- name: Uninstall setuptools
run: poetry run pip uninstall -y setuptools
- name: Install older setuptools
run: poetry run pip install 'setuptools<58.0.0'

# This command is a workaround for getting Poetry working with Python 3.10. An
# fix is made in Poetry 1.2.0a2 but there is currently no official release for
# Poetry 1.2 and am apprehensive to moving to a pre-release. Disabling the
# experimental installer is a workaround for Poetry 1.1.x
# See https://github.com/python-poetry/poetry/issues/4210 for more details
- name: Disable Poetry's experimental new installer
run: poetry config experimental.new-installer false

- name: Install dependencies
run: poetry install

- name: Add dummy data to icatdb
run: |
poetry run python -m util.icat_db_generator
# Run Nox tests session, saves and uploads a coverage report to codecov
- name: Run Nox tests session
run: nox -p ${{ matrix.python-version }} -s tests -- --cov=datagateway_api --cov-report=xml
- name: Upload code coverage report
# Run Nox integration tests session, saves and uploads a coverage report to codecov
- name: Run Nox Integration tests session
if: success()
run: nox -p ${{ matrix.python-version }} -s integration_tests -- --cov=datagateway_api --cov-report=xml
- name: Upload integration test code coverage report
if: matrix.python-version == '3.6'
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3

linting:
runs-on: ubuntu-20.04
Expand Down
39 changes: 26 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,12 @@ Currently, the following Nox sessions have been created:
- `safety` - this uses [safety](https://github.com/pyupio/safety) to check the
dependencies (pulled directly from Poetry) for any known vulnerabilities. This session
gives the output in a full ASCII style report.
- `tests` - this uses [pytest](https://docs.pytest.org/en/stable/) to execute the
automated tests in `test/`, tests for the database and ICAT backends, and non-backend
- `unit_tests` - this uses [pytest](https://docs.pytest.org/en/stable/) to execute the
automated tests in `test/unit`, tests for the database and ICAT backends, and non-backend
specific tests. More details about the tests themselves [here](#running-tests).
- `integration_tests` - this uses [pytest](https://docs.pytest.org/en/stable/) to execute the
automated tests in `test/unit`, tests for the database and ICAT backends, and non-backend
specific tests. Requires an ICAT backend. More details about the tests themselves [here](#running-tests).

Each Nox session builds an environment using the repo's dependencies (defined using
Poetry) using `install_with_constraints()`. This stores the dependencies in a
Expand Down Expand Up @@ -434,9 +437,14 @@ for the Swagger interface to be up to date when using the Python ICAT backend.

# Running Tests

To run the tests use `nox -s tests`. The repository contains a variety of tests, to test
the functionality of the API works as intended. The tests are split into 3 main
sections: non-backend specific (testing features such as the date handler), ICAT backend
There are two seperate test runners provided. The integration tests, and the unit tests.
The unit test do not require an ICAT stack to be setup to run. The integration tests do
require an ICAT stack. In order to cover all the code you will need to run both tests.

To run the unit test use `nox -s unit_tests`, and to run the integration tests use `nox -s integration_tests`
The repository contains a variety of tests, to test the functionality of the API works as intended, for convenience
and quicker action runs these are additionally split into the unit and integration tests.
The tests are split into 3 main sections: non-backend specific (testing features such as the date handler), ICAT backend
tests (containing tests for backend specific components, including tests for the
different types of endpoints) and Database Backend tests (like the ICAT backend tests,
but covering only the most used aspects of the API).
Expand All @@ -450,14 +458,16 @@ Python 3.6, 3.7, 3.8, 3.9 and 3.10. For most cases, running the tests in a singl
version will be sufficient:

```bash
nox -p 3.6 -s tests
nox -p 3.6 -s unit_tests
nox -p 3.6 -s integration
```

This repository also utilises [pytest-cov](https://pytest-cov.readthedocs.io/en/latest/)
to check how much of the codebase is covered by the tests in `test/`:

```bash
nox -p 3.6 -s tests -- --cov-report term --cov=./datagateway_api
nox -p 3.6 -s unit_tests -- --cov-report term --cov=./datagateway_api
nox -p 3.6 -s integration_tests -- --cov-report term --cov=./datagateway_api
```

With `pytest`, you can output the duration for each test, useful for showing the slower
Expand All @@ -466,21 +476,24 @@ into setup, call and teardown to more easily understand where the tests are bein
down:

```bash
nox -p 3.6 -s tests -- --durations=0
nox -p 3.6 -s unit_tests -- --durations=0
nox -p 3.6 -s integration_tests -- --durations=0
```

To test a specific test class (or even a specific test function), use a double colon to
denote a each level down beyond the filename:
To test a specific test class (or even a specific test function), you will
need to use pytest itself through poetry. If you want to change the python
version use `poetry env use 3.6` which will generate a virtual env with that
version.

```bash
# Test a specific file
nox -p 3.6 -s tests -- test/icat/test_query.py
poetry run pytest test/integration/datagateway_api/icat/test_query.py

# Test a specific test class
nox -p 3.6 -s tests -- test/icat/test_query.py::TestICATQuery
poetry run pytest test/integration/datagateway_api/icat/test_query.py::TestICATQuery

# Test a specific test function
nox -p 3.6 -s tests -- test/icat/test_query.py::TestICATQuery::test_valid_query_exeuction
poetry run pytest test/integration/datagateway_api/icat/test_query.py::TestICATQuery::test_valid_query_exeuction
```

# Project Structure
Expand Down
37 changes: 1 addition & 36 deletions datagateway_api/src/datagateway_api/icat/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from cachetools import cached
from dateutil.tz import tzlocal
from icat.entities import getTypeMap
from icat.exception import (
ICATInternalError,
ICATNoObjectError,
Expand Down Expand Up @@ -145,40 +144,6 @@ def refresh_client_session(client):
client.refresh()


def get_icat_entity_name_as_camel_case(client, entity_name):
"""
From the entity name, this function returns a camelCase version of its input
Due to the case sensitivity of Python ICAT, a camelCase version of the entity name
is required for creating ICAT entities in ICAT (e.g. `client.new("parameterType")`).
:param client: ICAT client containing an authenticated user
:type client: :class:`icat.client.Client`
:param entity_name: Entity name to fetch a camelCase version of
:type entity_name: :class:`str`
:return: Entity name (of type string) in the correct casing ready to be passed into
Python ICAT
:raises BadRequestError: If the entity cannot be found
"""

entity_names = getTypeMap(client).keys()
lowercase_entity_name = entity_name.lower()
python_icat_entity_name = None

for entity_name in entity_names:
lowercase_name = entity_name.lower()
if lowercase_name == lowercase_entity_name:
python_icat_entity_name = entity_name

# Raise a 400 if a valid entity cannot be found
if python_icat_entity_name is None:
raise BadRequestError(
f"Bad request made, cannot find {entity_name} entity within Python ICAT",
)

return python_icat_entity_name


def update_attributes(old_entity, new_entity):
"""
Updates the attribute(s) of a given object which is a record of an entity from
Expand Down Expand Up @@ -507,7 +472,7 @@ def create_entities(client, entity_type, data):
data = [data]

for result in data:
new_entity = client.new(get_icat_entity_name_as_camel_case(client, entity_type))
new_entity = client.new(entity_type.lower())

for attribute_name, value in result.items():
log.debug("Preparing data for %s", attribute_name)
Expand Down
35 changes: 32 additions & 3 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ def safety(session):
external=True,
)
# Ignore 50916 as the latest version of pydantic and
# Ignore 51457 as the latest version of pytest does not support
# Ignore 51457 as the latest version of pytest and
# Ignore 51668 as the latest version of SQLAchemy and
# Ignore 52355 and 52518 as the latest version of gitpython
# as they do not support
# python 3.6 which is still used in production
session.run(
"safety",
Expand All @@ -84,6 +87,12 @@ def safety(session):
"50916",
"--ignore",
"51457",
"--ignore",
"51668",
"--ignore",
"52322",
"--ignore",
"52518",
)

try:
Expand All @@ -95,7 +104,27 @@ def safety(session):


@nox.session(python=["3.6", "3.7", "3.8", "3.9", "3.10"], reuse_venv=True)
def tests(session):
def unit_tests(session):
args = session.posargs
# Installing setuptools that will work with `2to3` which is used when building
# `python-icat` < 1.0. 58.0.0 removes support of this tool during builds:
# https://setuptools.pypa.io/en/latest/history.html#v58-0-0
# Ideally this would be done within `pyproject.toml` but specifying `setuptools` as
# a dependency requires Poetry 1.2:
# https://github.com/python-poetry/poetry/issues/4511#issuecomment-922420457
# Currently, only a pre-release exists for Poetry 1.2. Testing on the pre-release
# version didn't fix the `2to3` issue when building Python ICAT, perhaps because
# Python ICAT isn't built on the downgraded version for some reason?
session.run("pip", "uninstall", "-y", "setuptools")
# Not using `poetry run` as it errors on Windows OS when a version with the '<'
# sign is specified for a package
session.run("pip", "install", "setuptools<58.0.0")
session.run("poetry", "install", external=True)
session.run("pytest", "test/unit", *args)


@nox.session(python=["3.6", "3.7", "3.8", "3.9", "3.10"], reuse_venv=True)
def integration_tests(session):
args = session.posargs
# Installing setuptools that will work with `2to3` which is used when building
# `python-icat` < 1.0. 58.0.0 removes support of this tool during builds:
Expand All @@ -111,4 +140,4 @@ def tests(session):
# sign is specified for a package
session.run("pip", "install", "setuptools<58.0.0")
session.run("poetry", "install", external=True)
session.run("pytest", *args)
session.run("pytest", "test/integration", *args)
Loading

0 comments on commit b08022a

Please sign in to comment.