Skip to content

Commit

Permalink
Make separate test environments for full version and minimal version …
Browse files Browse the repository at this point in the history
…without dependencies

A new environment for testing only with core dependencies installed is added to the ci_tests workflow.

All tests are moved to separate functions instead of test scripts.

Tests that require additiona  dependencies are skipped if the required dependency is not installed.
  • Loading branch information
francescalb committed Oct 19, 2023
2 parents 3212e48 + 3533c5b commit f9f43c0
Show file tree
Hide file tree
Showing 13 changed files with 532 additions and 410 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,30 @@ jobs:
- name: Run doctest on tutorial
run: |
python -m doctest docs/tutorial.md
pytest-no-extra-dependencies: # Test for basic version, without extras installed
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]

steps:
- name: Checkout tripper
uses: actions/checkout@v4

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

- name: Install dependencies
run: |
sudo apt install graphviz
python -m pip install -U pip
pip install -U setuptools wheel flit
pip install -e .[testing-core]
- name: Test with pytest, but without other extra dependencies
run: pytest -vvv tests/
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ testing = [
"DLite-Python >=0.4.0,<1",
"graphviz ~= 0.20",
]
testing-core = [
"pytest ~=7.4",
"pytest-cov ~=4.1",
]
dev = [
"mike ~=1.1",
"mkdocs ~=1.5",
Expand Down
112 changes: 59 additions & 53 deletions tests/convert/test_convert.py
Original file line number Diff line number Diff line change
@@ -1,55 +1,61 @@
"""Test convertions."""
# pylint: disable=invalid-name
from tripper import Triplestore
from tripper.convert import load_container, save_container

ts = Triplestore(backend="rdflib")
EX = ts.bind("ex", "http://example.com/ex#")


config1 = {
"downloadUrl": "http://example.com/somedata.txt",
"mediaType": "application/text",
"anotherField": "More info...",
}

config2 = {
"downloadUrl": "http://example.com/somedata.txt",
"mediaType": "application/text",
"anotherField": "More info...",
"configurations": {
"key1": "val1",
"key2": 2,
"key3": 3.14,
"key4": None,
"key5": True,
"key6": False,
"key7": ["a", 1, 2.2, True, None],
},
}

# Store dictionaries to triplestore
save_container(ts, config1, EX.config1)
save_container(ts, config2, EX.config2)

# Print content of triplestore
# print(ts.serialize())

# Load dictionaries from triplestore
d1 = load_container(ts, EX.config1)
d2 = load_container(ts, EX.config2)

# Check that we got back what we stored
assert d1 == config1
assert d2 == config2


# Now, test serialising using recognised_keys
save_container(ts, config1, EX.config1b, recognised_keys="basic")
save_container(ts, config2, EX.config2b, recognised_keys="basic")

d1b = load_container(ts, EX.config1b, recognised_keys="basic")
d2b = load_container(ts, EX.config2b, recognised_keys="basic")

assert d1b == config1
assert d2b == config2

import pytest


def test_convertions():
"""Test convertions. Uses rdflib as triplestore backend"""

pytest.importorskip("rdflib")
from tripper import Triplestore
from tripper.convert import load_container, save_container

ts = Triplestore(backend="rdflib")
EX = ts.bind("ex", "http://example.com/ex#")

config1 = {
"downloadUrl": "http://example.com/somedata.txt",
"mediaType": "application/text",
"anotherField": "More info...",
}

config2 = {
"downloadUrl": "http://example.com/somedata.txt",
"mediaType": "application/text",
"anotherField": "More info...",
"configurations": {
"key1": "val1",
"key2": 2,
"key3": 3.14,
"key4": None,
"key5": True,
"key6": False,
"key7": ["a", 1, 2.2, True, None],
},
}

# Store dictionaries to triplestore
save_container(ts, config1, EX.config1)
save_container(ts, config2, EX.config2)

# Print content of triplestore
# print(ts.serialize())

# Load dictionaries from triplestore
d1 = load_container(ts, EX.config1)
d2 = load_container(ts, EX.config2)

# Check that we got back what we stored
assert d1 == config1
assert d2 == config2

# Now, test serialising using recognised_keys
save_container(ts, config1, EX.config1b, recognised_keys="basic")
save_container(ts, config2, EX.config2b, recognised_keys="basic")

d1b = load_container(ts, EX.config1b, recognised_keys="basic")
d2b = load_container(ts, EX.config2b, recognised_keys="basic")

assert d1b == config1
assert d2b == config2
61 changes: 33 additions & 28 deletions tests/mappings/test_function.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,47 @@
"""Test mapping function.
"""Test mapping function."""

We have two data sources:
- literal number 3.2 mapped to ex:A
- vector mapped to ex:B

We also have two mapping functions; first() and sum()
- first(): ex:B[0] -> ex:C
- sum(): ex:A + ex:C -> ex:D
def test_mapping():
"""Test mapping function.
The test asks for the value of an individual of ex:D
"""
# pylint: disable=unused-argument,invalid-name
from tripper import Literal, Tripper
We have two data sources:
- literal number 3.2 mapped to ex:A
- vector mapped to ex:B
tp = Tripper(backend="rdflib")
EX = tp.bind("ex", "http://example.com/onto#")
We also have two mapping functions; first() and sum()
- first(): ex:B[0] -> ex:C
- sum(): ex:A + ex:C -> ex:D
The test asks for the value of an individual of ex:D
def first(vector):
"""Return first element of the vector."""
return vector[0]
Uses rdflib as backend
"""
# pylint: disable=unused-argument,invalid-name
import pytest

pytest.importorskip("rdflib")
from tripper import Literal, Tripper

def add(a, b):
"""Return the sum of `a` and `b`."""
return a + b
tp = Tripper(backend="rdflib")
EX = tp.bind("ex", "http://example.com/onto#")

def first(vector):
"""Return first element of the vector."""
return vector[0]

def vector(iri, configurations, triplestore):
"""Return a vector."""
return [0.5, 1.2, 3.4, 6.6]
def add(a, b):
"""Return the sum of `a` and `b`."""
return a + b

def vector(iri, configurations, triplestore):
"""Return a vector."""
return [0.5, 1.2, 3.4, 6.6]

tp.add_data(Literal(3.2), EX.A)
tp.add_data(vector, EX.B)
tp.add_data(Literal(3.2), EX.A)
tp.add_data(vector, EX.B)

tp.add_function(first, expects=EX.B, returns=EX.C)
tp.add_function(add, expects=(EX.A, EX.C), returns=EX.D)
tp.add_function(first, expects=EX.B, returns=EX.C)
tp.add_function(add, expects=(EX.A, EX.C), returns=EX.D)

tp.map(EX.indv, EX.D)
assert tp.get_value(EX.indv) == 3.7
tp.map(EX.indv, EX.D)
assert tp.get_value(EX.indv) == 3.7
71 changes: 38 additions & 33 deletions tests/mappings/test_mappings.py
Original file line number Diff line number Diff line change
@@ -1,52 +1,57 @@
#!/usr/bin/env python
"""Test mappings."""
from pathlib import Path

from tripper import Triplestore
from tripper.mappings import mapping_routes
# pylint: disable=invalid-name

# Configure paths
thisdir = Path(__file__).parent.absolute()
import pytest

ts = Triplestore(backend="rdflib")

def test_mappings():
"""Test mappings.
Uses rdflib as backend
"""

# Define some prefixed namespaces
CHEM = ts.bind("chem", "http://onto-ns.com/onto/chemistry#")
MOL = ts.bind("mol", "http://onto-ns.com/meta/0.1/Molecule#")
MOL2 = ts.bind("mol2", "http://onto-ns.com/meta/0.1/Molecule2#")
SUB = ts.bind("sub", "http://onto-ns.com/meta/0.1/Substance#")
pytest.importorskip("rdflib")

from tripper import Triplestore
from tripper.mappings import mapping_routes

# Add mappings from data models to ontology
ts.add_mapsTo(CHEM.Identifier, MOL.name)
ts.add_mapsTo(CHEM.Identifier, SUB.id)
ts = Triplestore(backend="rdflib")

ts.add_mapsTo(CHEM.GroundStateEnergy, MOL.groundstate_energy)
ts.add_mapsTo(CHEM.GroundStateEnergy, MOL2.energy)
ts.add_mapsTo(CHEM.GroundStateEnergy, SUB.molecule_energy)
# Define some prefixed namespaces
CHEM = ts.bind("chem", "http://onto-ns.com/onto/chemistry#")
MOL = ts.bind("mol", "http://onto-ns.com/meta/0.1/Molecule#")
MOL2 = ts.bind("mol2", "http://onto-ns.com/meta/0.1/Molecule2#")
SUB = ts.bind("sub", "http://onto-ns.com/meta/0.1/Substance#")

# Add mappings from data models to ontology
ts.add_mapsTo(CHEM.Identifier, MOL.name)
ts.add_mapsTo(CHEM.Identifier, SUB.id)

routes = mapping_routes(
target=SUB.molecule_energy,
sources={MOL.groundstate_energy: 1.0},
triplestore=ts,
)
ts.add_mapsTo(CHEM.GroundStateEnergy, MOL.groundstate_energy)
ts.add_mapsTo(CHEM.GroundStateEnergy, MOL2.energy)
ts.add_mapsTo(CHEM.GroundStateEnergy, SUB.molecule_energy)

assert routes.number_of_routes() == 1
assert routes.output_iri == (
"http://onto-ns.com/meta/0.1/Substance#molecule_energy"
)
assert routes.cost == 2.0
assert (
routes.visualise(0).strip()
== """
routes = mapping_routes(
target=SUB.molecule_energy,
sources={MOL.groundstate_energy: 1.0},
triplestore=ts,
)

assert routes.number_of_routes() == 1
assert routes.output_iri == (
"http://onto-ns.com/meta/0.1/Substance#molecule_energy"
)
assert routes.cost == 2.0
assert (
routes.visualise(0).strip()
== """
digraph G {
"mol:groundstate_energy" -> "chem:GroundStateEnergy" [label="mapsTo"];
"chem:GroundStateEnergy" -> "sub:molecule_energy" [label="inverse(mapsTo)"];
}
""".strip()
)
)

# Commented out, to avoid dependencies of Graphviz
# routes.visualise(0, output="graph.png", format="png", dot="dot")
# Commented out, to avoid dependencies of Graphviz
# routes.visualise(0, output="graph.png", format="png", dot="dot")
Loading

0 comments on commit f9f43c0

Please sign in to comment.