diff --git a/.github/workflows/pandora2d_ci.yml b/.github/workflows/pandora2d_ci.yml index a42d89e..5d3fbb2 100644 --- a/.github/workflows/pandora2d_ci.yml +++ b/.github/workflows/pandora2d_ci.yml @@ -23,6 +23,7 @@ jobs: pip install pytest pip install pytest-cov pip install pytest-mock + pip install pytest-html pip install codecov pip install build - name: Install Pandora2d @@ -31,7 +32,8 @@ jobs: - name: Test with pytest run: | export NUMBA_DISABLE_JIT="1" - pytest --junitxml=pytest-report.xml --cov-config=.coveragerc --cov-report xml --cov + pytest -m "unit_tests" --html=unit-test-report.html --cov-config=.coveragerc --cov-report xml --cov + pytest -m "functional_tests" --html=functional-test-report.html - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 - name: Create source distrubition diff --git a/.gitignore b/.gitignore index 68bc17f..f3b353a 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,9 @@ coverage.xml .pytest_cache/ cover/ +# Monitoring test +.pymon + # Translations *.mo *.pot diff --git a/Makefile b/Makefile index 5ba1908..85717a8 100644 --- a/Makefile +++ b/Makefile @@ -61,8 +61,32 @@ install: venv ## install pandora2D (pip editable mode) without plugins ## Test section .PHONY: test -test: install ## run all tests (except notebooks) + coverage (source venv before) - @${PANDORA2D_VENV}/bin/pytest --junitxml=pytest-report.xml --cov-config=.coveragerc --cov-report xml --cov +test: install test-unit test-functional ## run unit tests and functional tests + +.PHONY: test-all +test-all: install test-unit test-functional test-resource test-performance ## run all tests + +.PHONY: test-unit +test-unit: install ## run unit tests only (for dev) + coverage (source venv before) + @echo "Run unit tests" + @${PANDORA2D_VENV}/bin/pytest -m "unit_tests" --html=unit-test-report.html --cov-config=.coveragerc --cov-report xml --cov + +.PHONY: test-functional +test-functional: install ## run functional tests only (for dev and validation plan) + @echo "Run functional tests" + @${PANDORA2D_VENV}/bin/pytest -m "functional_tests" --html=functional-test-report.html + +.PHONY: test-resource +test-resource: install ## run resource tests only (for validation plan) + @echo "Run resource tests" + @rm -f tests/resource_tests/.pymon + @${PANDORA2D_VENV}/bin/pytest -m "resource_tests and not metrics" --db tests/resource_tests/.pymon + @${PANDORA2D_VENV}/bin/pytest tests/resource_tests/test_metrics.py --database tests/resource_tests/.pymon --html=resource-test-report.html + +.PHONY: test-performance +test-performance: install ## run performance tests only (for validation plan) + @echo "Run performance tests" + @${PANDORA2D_VENV}/bin/pytest -m "performance_tests" --html=performance-test-report.html ## Code quality, linting section @@ -94,7 +118,7 @@ lint/mypy: ## check linting with mypy .PHONY: lint/pylint lint/pylint: ## check linting with pylint @echo "+ $@" - @set -o pipefail; ${PANDORA2D_VENV}/bin/pylint pandora2d "tests/*" --rcfile=.pylintrc --output-format=parseable --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" # | tee pylint-report.txt # pipefail to propagate pylint exit code in bash + @set -o pipefail; ${PANDORA2D_VENV}/bin/pylint pandora2d tests ./*.py --rcfile=.pylintrc --output-format=parseable --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" # | tee pylint-report.txt # pipefail to propagate pylint exit code in bash ## Documentation section @@ -158,9 +182,11 @@ clean-test: @rm -rf coverage.xml @rm -fr htmlcov/ @rm -fr .pytest_cache - @rm -f pytest-report.xml @rm -f pylint-report.txt @rm -f debug.log + @rm -f .pymon + @rm -f tests/resource_tests/.pymon + @rm -f *-test-report.html .PHONY: clean-doc clean-doc: diff --git a/pandora2d/img_tools.py b/pandora2d/img_tools.py index 8b41e3b..2b8c369 100644 --- a/pandora2d/img_tools.py +++ b/pandora2d/img_tools.py @@ -30,9 +30,9 @@ import xarray as xr import numpy as np +from scipy.ndimage import shift import pandora.img_tools as pandora_img_tools -from scipy.ndimage import shift class Datasets(NamedTuple): diff --git a/pytest.ini b/pytest.ini index b9eb999..84f2eed 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,4 +1,10 @@ [pytest] -addopts = -ra +addopts = -ra --parametrization-explicit testpaths = tests -norecursedirs = .git doc conf .gitlab \ No newline at end of file +markers = + unit_tests: unit tests + functional_tests: functional tests + resource_tests: resource tests + performance_tests: accuracy tests +norecursedirs = .git doc conf .gitlab +generate_report_on_test = True \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index a5ee30d..1d053dc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -77,6 +77,8 @@ dev = pytest pytest-cov pytest-mock + pytest-monitor + pytest-html pre-commit isort>=5.8.0 # Check imports black>=21.5b0 # PEP8 format code diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..f6f29a2 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,79 @@ +# Description +This directory contains the different tests to validate Pandora2D. + +# Tests + +## Directory +The Pandora2D test cases correspond to the following tree structure: + +- unit_tests : TU + - A TU validates a function as a unit. + - A TU does not necessarily meet a customer requirement because a function can meet a technical need (as opposed to a user need). +- functional_tests : TF + - A TF validates the end-to-end operation of Pandora2D and therefore, potentially, the combination of several parameters. + - A TF meets one or more customer requirements (user needs). + - A matrix representing the scenarios and operating requirements to be met is presented in each sub-directory. +- performance_tests : TP + - A practical work session validates the accuracy that Pandora2D can achieve in the field (essentially, the accuracy of alignment). + - A TP can meet a customer requirement or be provided for information purposes. +- resource_tests : TR + - A TR validates the machine resources (time/occupancy and memory) required by Pandora2D for end-to-end operation. + - A TR may meet a customer requirement or be provided for information purposes. + +## Functionality +It's the primary function validated by this test case. The list below shows the different functionalities tested : + +- target_grid : l'utilisateur peut avoir recours à une roi ou à un pas +- mode : the type of search +- criteria : invalidity indicators are raised depending on the calculation on the pixel in question (use of masks, area of disparity too large, etc.) +- matching_cost : the stage where a similarity score is calculated between the two images. +- disparity : selecting the best similarity score, for the moment there is only the WTA method (Winner takes all). +- refinement : accurate the disparity to smooth outliers. +- validation : a criterion that gives the user additional confidence in the result. + +These different functionalities are then divided into sub-functionalities which will be described in the xx file. +A folder is created for each functionality/sub-functionality. + +## Docstring template for test +For each test, a full description with name, id and data is included in the function's docstring. Below is the template: + +```python +""" + + +ID : +name : +input : +""" +``` + +with category which can take the following values: +- TU +- TF +- TP +- TR + +## Test execution +There are several options for launching the various tests: + +1. Using the `Makefile`: the different targets defined + - `make test` : run unit tests and functional tests + - `make test-all` : run all tests in this directory and sub-directory + - `make test-unit` : run unit tests only + - `make test-functional` : run functional tests only + - `make test-resource` : run resource tests only + - `make test-performance` : run performance only + +2. Using the command line with pytest with virtual environment `venv` directory: + ```shell + source venv/bin/active ## active venv + pytest -m " or " --parametrization-explicit -vv ## Using a target defined in pytest.ini + ``` + +## Monitoring test +The aim is to check the execution time of certain tests as well as the CPU and memory load. pytest-monitor has been used to check this, see the [page](https://pypi.org/project/pytest-monitor/) for more information. + +:exclamation: Only the tests in resource_tests directory use the monitoring. + +# Data (Coming soon) +At present, only 'cone' images are used for unit tests. \ No newline at end of file diff --git a/tests/common.py b/tests/common.py deleted file mode 100644 index f42a3d5..0000000 --- a/tests/common.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python -# coding: utf8 -# -# Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). -# Copyright (c) 2024 CS GROUP France -# -# This file is part of PANDORA2D -# -# https://github.com/CNES/Pandora2D -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -""" -This module contains common functions present in Pandora2D's tests. -""" - -correct_input = { - "input": { - "left": { - "img": "./tests/data/left.png", - "nodata": "NaN", - }, - "right": { - "img": "./tests/data/right.png", - }, - "col_disparity": [-2, 2], - "row_disparity": [-2, 2], - } -} - - -false_input_path_image = { - "input": { - "left": { - "img": "./tests/data/lt.png", - "nodata": "NaN", - }, - "right": { - "img": "./tests/data/right.png", - }, - "col_disparity": [-2, 2], - "row_disparity": [-2, 2], - } -} - -false_input_disp = { - "input": { - "left": { - "img": "./tests/data/left.png", - }, - "right": { - "img": "./tests/data/right.png", - }, - "col_disparity": [7, 2], - "row_disparity": [-2, 2], - } -} - -correct_pipeline = { - "pipeline": { - "estimation": {"estimation_method": "phase_cross_correlation"}, - "matching_cost": {"matching_cost_method": "zncc", "window_size": 5}, - "disparity": {"disparity_method": "wta", "invalid_disparity": -99}, - "refinement": {"refinement_method": "interpolation"}, - } -} - -false_pipeline_mc = { - "pipeline": { - "disparity": {"disparity_method": "wta", "invalid_disparity": -99}, - "refinement": {"refinement_method": "interpolation"}, - } -} - -false_pipeline_disp = { - "pipeline": { - "matching_cost": {"matching_cost_method": "zncc", "window_size": 5}, - "refinement": {"refinement_method": "interpolation"}, - } -} - -correct_ROI_sensor = { - "ROI": { - "col": {"first": 10, "last": 100}, - "row": {"first": 10, "last": 100}, - } -} - -false_ROI_sensor_negative = { - "ROI": { - "col": {"first": -10, "last": 100}, - "row": {"first": 10, "last": 100}, - } -} - -false_ROI_sensor_first_superior_to_last = { - "ROI": { - "col": {"first": 110, "last": 100}, - "row": {"first": 10, "last": 100}, - } -} diff --git a/tests/conftest.py b/tests/conftest.py index 65aa984..9428ca5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,19 +1,79 @@ -""" Module with global test fixtures. """ - -from copy import deepcopy +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). +# +# This file is part of PANDORA2D +# +# https://github.com/CNES/Pandora2D +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" +Module with global test fixtures. +""" +import pathlib +import re import pytest -from pandora2d import Pandora2DMachine -from tests import common +def pytest_collection_modifyitems(config, items): + """ + Update marker collections -@pytest.fixture() -def pandora2d_machine(): - """pandora2d_machine""" - return Pandora2DMachine() + 1. Adds the marker corresponding to the various directories ending in "_test". + The various markers created are: + - unit_tests + - functional_tests + - performance_tests + - resource_tests + 2. Disables pytest_monitor. + """ + rootdir = pathlib.Path(config.rootdir) + for item in items: + rel_path = pathlib.Path(item.fspath).relative_to(rootdir) + mark_name = next((part for part in rel_path.parts if part.endswith("_tests")), "") + if mark_name: + mark = getattr(pytest.mark, mark_name) + item.add_marker(mark) + item.add_marker(pytest.mark.monitor_skip_test) + + +def pytest_html_results_table_header(cells): + """ + Add columns to html reports: + + 1. Category : with values {'TU', 'TF', 'TP', 'TR'} + 2. Function tested : basename of python test file + """ + cells.insert(1, "Category") + cells.insert(2, "Function tested") + + +def pytest_html_results_table_row(report, cells): + """ + Complete columns to html reports with regex pattern : + + "tests/_tests/.../tests_.py::tests" + + 1. CATEGORY : with values {'TU', 'TF', 'TP', 'TR'} + 2. FUNCTION : basename of python test file + """ + type_dict = {"unit": "TU", "functional": "TF", "resource": "TR", "performance": "TP"} + pattern = r"tests/(?P\w+)_tests.*test_(?P\w+)\.py" + match = re.match(pattern, report.nodeid) + cells.insert(1, f"{type_dict[match.groupdict()['type']]}") + cells.insert(2, f"{match.groupdict()['function']}") @pytest.fixture() -def pipeline_config(): - return deepcopy(common.correct_pipeline) +def classic_config(): + return "./tests/data/json_conf_files/classic_cfg.json" diff --git a/tests/data/left.png b/tests/data/images/cones/left.png similarity index 100% rename from tests/data/left.png rename to tests/data/images/cones/left.png diff --git a/tests/data/right.png b/tests/data/images/cones/right.png similarity index 100% rename from tests/data/right.png rename to tests/data/images/cones/right.png diff --git a/tests/data/json_conf_files/classic_cfg.json b/tests/data/json_conf_files/classic_cfg.json new file mode 100644 index 0000000..351bc15 --- /dev/null +++ b/tests/data/json_conf_files/classic_cfg.json @@ -0,0 +1,26 @@ +{ + "input": { + "left": { + "img": "./tests/data/images/cones/left.png", + "nodata": "NaN" + }, + "right": { + "img": "./tests/data/images/cones/right.png" + }, + "col_disparity": [-2, 2], + "row_disparity": [-2, 2] + }, + "pipeline": { + "matching_cost": { + "matching_cost_method": "zncc", + "window_size": 5 + }, + "disparity": { + "disparity_method": "wta", + "invalid_disparity": -99 + }, + "refinement": { + "refinement_method": "interpolation" + } + } +} \ No newline at end of file diff --git a/tests/functional_tests/README.md b/tests/functional_tests/README.md new file mode 100644 index 0000000..c58d697 --- /dev/null +++ b/tests/functional_tests/README.md @@ -0,0 +1,111 @@ +# Definition + +A non-regression test below is used to validate each function of the Pandora2D tool and to ensure that future developments will not lead back to an earlier stage. + +# Functionality +For each functionality, a directory is created. Theses functionalities are as follows. + +## Target Grid +The target grid is the processing area in pandora2d. This can be an area or certain pixels. The sub-functionalities tested here are: + ++-------------------+---------------------------------------------------------------------------------+ +| Sub-functionality | Description | ++-------------------+---------------------------------------------------------------------------------+ +| roi | A ROI (region of interest) is a polygon representing the image to be processed. | ++-------------------+---------------------------------------------------------------------------------+ +| step | A step can be used to avoid processing all the pixels. | ++-------------------+---------------------------------------------------------------------------------+ + +## Mode +The mode is the type of search (example : disparity range). The sub-functionalities tested here are: + ++------------------------+---------------------------------------------------------------------+ +| Sub-functionality | Description | ++------------------------+---------------------------------------------------------------------+ +| multiscale | An image pyramid is computed according to the given scale factor | ++------------------------+---------------------------------------------------------------------+ +| strip | A large image cut into sub-images with the roi | ++------------------------+---------------------------------------------------------------------+ +| initial_disparity | A search with a fixed pixel disparity | ++------------------------+---------------------------------------------------------------------+ +| initial_disparity_grid | A search with disparity grid, i.e. a fixed disparity for each pixel | ++------------------------+---------------------------------------------------------------------+ +| exploration_pix | A research zone around a disparity | ++------------------------+---------------------------------------------------------------------+ +| exploration_grid | A research zone grid, i.e. an exploration for each pixel | ++------------------------+---------------------------------------------------------------------+ +| subpix | A more accurate search for disparities | ++------------------------+---------------------------------------------------------------------+ + +## Criteria +Invalidity indicators are raised depending on the calculation on the pixel in question (use of masks, area of disparity too large, etc.). The sub-functionalities tested here are: + ++----------------------+-----------------------------------------------------------------+ +| Sub-functionality | Description | ++----------------------+-----------------------------------------------------------------+ +| left_mask | Using a mask on the left image | ++----------------------+-----------------------------------------------------------------+ +| right_mask | Using a mask on the right image | ++----------------------+-----------------------------------------------------------------+ +| no_data_left | Some pixels contain no data on the left image | ++----------------------+-----------------------------------------------------------------+ +| no_data_right | Some pixels contain no data on the right image | ++----------------------+-----------------------------------------------------------------+ +| disparity_range | The disparity search zone is too large | ++----------------------+-----------------------------------------------------------------+ +| matching_cost_window | The window size of matching cost algorithm is outside the image | ++----------------------+-----------------------------------------------------------------+ + +## Matching_cost +This is the stage where a similarity score is calculated between the two images. The algorithms tested here are: + ++-----------+----------------------------------------+ +| Algorithm | Description | ++-----------+----------------------------------------+ +| zncc | Zero mean Normalized Cross Correlation | ++-----------+----------------------------------------+ +| sad | Sum of Absolute Differences | ++-----------+----------------------------------------+ +| ssd | Sum of Squared Differences | ++-----------+----------------------------------------+ +| MI | Mutual Information | ++-----------+----------------------------------------+ + +## Disparity +Selecting the best similarity score, for the moment there is only the WTA method (Winner takes all). + +## Refinement +Accurate the disparity to smooth outliers. The algorithms tested here are: + ++-----------+-----------------------+ +| Algorithm | Description | ++-----------+-----------------------+ +| fo | Optical flow | ++-----------+-----------------------+ +| dichotomy | Reseach by dichotomy | ++-----------+-----------------------+ +| bicubic | Bicubic interpolation | ++-----------+-----------------------+ +| sinc | Sinux cardinal | ++-----------+-----------------------+ +| spline | Spline | ++-----------+-----------------------+ + +## Validation +A criterion that gives the user additional confidence in the result. The algorithms tested here are: + ++---------------------+----------------------------------+ +| Algorithm | Description | ++---------------------+----------------------------------+ +| validation_fast | as its name suggests | ++---------------------+----------------------------------+ +| validation_accurate | as its name suggests | ++---------------------+----------------------------------+ +| border_pic | Ambiguity indicator | ++---------------------+----------------------------------+ +| fo_diverge | in connection with optical flows | ++---------------------+----------------------------------+ +| fo_hess | in connection with optical flows | ++---------------------+----------------------------------+ +| fo_eigenval | in connection with optical flows | ++---------------------+----------------------------------+ \ No newline at end of file diff --git a/tests/functional_tests/__init__.py b/tests/functional_tests/__init__.py new file mode 100644 index 0000000..a79c48d --- /dev/null +++ b/tests/functional_tests/__init__.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). +# +# This file is part of PANDORA2D +# +# https://github.com/CNES/Pandora2D +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/tests/functional_tests/target_grid/roi/test_example.py b/tests/functional_tests/target_grid/roi/test_example.py new file mode 100644 index 0000000..3a9dd84 --- /dev/null +++ b/tests/functional_tests/target_grid/roi/test_example.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). +# +# This file is part of PANDORA2D +# +# https://github.com/CNES/Pandora2D +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +""" +Tests +""" + +from contextlib import nullcontext as does_not_raise + +import sys +import pytest + + +class TestExample: + """ + Examples + """ + + @pytest.mark.parametrize( + ("n", "expected"), + [ + (1, 2), + pytest.param(1, 0, marks=pytest.mark.xfail), + pytest.param(1, 3, marks=pytest.mark.xfail(reason="some bug")), + (2, 3), + (3, 4), + (4, 5), + pytest.param(10, 11, marks=pytest.mark.skipif(sys.version_info >= (3, 0), reason="py2k")), + ], + ) + def test_increment(self, n, expected): + """ + Test with xfail and skipif + """ + assert n + 1 == expected + + @pytest.mark.parametrize( + "example_input,expectation", + [ + (3, does_not_raise()), + (2, does_not_raise()), + (1, does_not_raise()), + (0, pytest.raises(ZeroDivisionError)), + ], + ) + def test_division(self, example_input, expectation): + """Test how much I know division.""" + with expectation: + assert (6 / example_input) is not None diff --git a/tests/performance_tests/__init__.py b/tests/performance_tests/__init__.py new file mode 100644 index 0000000..a79c48d --- /dev/null +++ b/tests/performance_tests/__init__.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). +# +# This file is part of PANDORA2D +# +# https://github.com/CNES/Pandora2D +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/tests/resource_tests/README.md b/tests/resource_tests/README.md new file mode 100644 index 0000000..45072c0 --- /dev/null +++ b/tests/resource_tests/README.md @@ -0,0 +1,13 @@ +# Definition + +A test on memory/CPU consumption gives indications of the minimum resources required for Pandora2D to operate nominally. +For these tests, the pytest-monitor library is used to obtain the information in a sqlite3 database, a *.pymon* file. + +To run all the monitored tests, use the following command line: +``` +make test-resource +``` + +This command launches the first test_example.py script, which runs the resource tests. Then a second script, test_metrics.py, reads the database and checks that the metrics are respected. + +:warning: The values of the various metrics will be set at a later date. diff --git a/tests/resource_tests/__init__.py b/tests/resource_tests/__init__.py new file mode 100644 index 0000000..a79c48d --- /dev/null +++ b/tests/resource_tests/__init__.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). +# +# This file is part of PANDORA2D +# +# https://github.com/CNES/Pandora2D +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/tests/resource_tests/conftest.py b/tests/resource_tests/conftest.py new file mode 100644 index 0000000..de69983 --- /dev/null +++ b/tests/resource_tests/conftest.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). +# +# This file is part of PANDORA2D +# +# https://github.com/CNES/Pandora2D +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" +Module with global test fixtures. +""" +from typing import List +import sqlite3 +import pytest + + +class Metrics: + """ + Metrics Class + """ + + # pylint:disable=too-few-public-methods + + _TOTAL_TIME_MAX = 120 # second + _CPU_USAGE_MAX = 50 # percent + _MEM_USAGE_MAX = 1024 # megabyte + + def __init__(self, items: List) -> None: + self.test_name = items[0] + self.total_time = items[1] + self.cpu_usage = items[2] + self.mem_usage = items[3] + + +def pytest_addoption(parser): + parser.addoption("--database", action="store", default=".pymon", required=False) + + +@pytest.fixture(name="database_path") +def database_path_fixture(request): + return request.config.getoption("--database") + + +@pytest.fixture +def output_result_path(): + return "./tests/resource_tests/result" + + +@pytest.fixture(name="sqlite_select_query") +def sqlite_select_query_fixture(): + return """SELECT ITEM, TOTAL_TIME, CPU_USAGE, MEM_USAGE FROM TEST_METRICS""" + + +@pytest.fixture() +def read_sqlite_table(database_path, sqlite_select_query): + """ + Read sqlite table from pytest-monitoring + """ + data = [] + try: + sqlite_connection = sqlite3.connect(database_path) + cursor = sqlite_connection.cursor() + + cursor.execute(sqlite_select_query) + records = cursor.fetchall() + data = [Metrics(record) for record in records] + sqlite_connection.close() + except sqlite3.Error as error: + print("Failed to read data from sqlite table", error) + return data diff --git a/tests/resource_tests/test_example.py b/tests/resource_tests/test_example.py new file mode 100644 index 0000000..dc48e4d --- /dev/null +++ b/tests/resource_tests/test_example.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). +# +# This file is part of PANDORA2D +# +# https://github.com/CNES/Pandora2D +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +""" +Test example for resources +""" + +import pytest +import pandora2d + + +@pytest.mark.monitor_test +class TestConeImage: + """Test pandora with cone image.""" + + # pylint:disable=too-few-public-methods + + def test_pandora(self, classic_config, output_result_path): + """ + Test run pandora with cone images + """ + pandora2d.main(classic_config, output_result_path, True) diff --git a/tests/resource_tests/test_metrics.py b/tests/resource_tests/test_metrics.py new file mode 100644 index 0000000..6008a28 --- /dev/null +++ b/tests/resource_tests/test_metrics.py @@ -0,0 +1,61 @@ +# pylint: disable=protected-access +#!/usr/bin/env python +# +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). +# +# This file is part of PANDORA2D +# +# https://github.com/CNES/Pandora2D +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +""" +This module is used to check the resources used for the tests in this directory. +""" +import pytest + + +@pytest.mark.metrics +@pytest.mark.monitor_skip_test +class TestResource: + """ + Test all tests are ok for CPU/MEM and time rule + """ + + def test_total_time(self, read_sqlite_table): + """ + Verify the time metrics for the test + """ + for metric in read_sqlite_table: + assert ( + metric.total_time < metric._TOTAL_TIME_MAX + ), f"Test {metric.test_name} does not respect max time : {metric._TOTAL_TIME_MAX} (seconds)" + + def test_cpu_usage(self, read_sqlite_table): + """ + Verify the cpu metrics for the test + """ + for metric in read_sqlite_table: + assert ( + metric.cpu_usage < metric._CPU_USAGE_MAX + ), f"Test {metric.test_name} does not cpu usage max : {metric._CPU_USAGE_MAX} (%)" + + def test_mem_usage(self, read_sqlite_table): + """ + Verify the memory metrics for the test + """ + for metric in read_sqlite_table: + assert ( + metric.mem_usage < metric._MEM_USAGE_MAX + ), f"Test {metric.test_name} does not respect memory usage max : {metric._MEM_USAGE_MAX} (megabyte)" diff --git a/tests/unit_tests/README.md b/tests/unit_tests/README.md new file mode 100644 index 0000000..d31afef --- /dev/null +++ b/tests/unit_tests/README.md @@ -0,0 +1,3 @@ +# Definition + +A unit test is used to validate a given function implemented in Pandora2D. It validates its nominal and/or boundary behaviour. diff --git a/tests/__init__.py b/tests/unit_tests/__init__.py similarity index 97% rename from tests/__init__.py rename to tests/unit_tests/__init__.py index 7577454..3ba87c5 100644 --- a/tests/__init__.py +++ b/tests/unit_tests/__init__.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf8 # # Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). # diff --git a/tests/unit_tests/conftest.py b/tests/unit_tests/conftest.py new file mode 100644 index 0000000..9bab791 --- /dev/null +++ b/tests/unit_tests/conftest.py @@ -0,0 +1,139 @@ +""" Module with global test fixtures. """ + +from copy import deepcopy + +import pytest + +from pandora2d import Pandora2DMachine + + +@pytest.fixture() +def pandora2d_machine(): + """pandora2d_machine""" + return Pandora2DMachine() + + +@pytest.fixture() +def pipeline_config(correct_pipeline): + return deepcopy(correct_pipeline) + + +@pytest.fixture(name="left_img_path") +def left_img_path_fixture(): + return "./tests/data/images/cones/left.png" + + +@pytest.fixture(name="right_img_path") +def right_img_path_fixture(): + return "./tests/data/images/cones/right.png" + + +@pytest.fixture +def correct_input_cfg(left_img_path, right_img_path): + return { + "input": { + "left": { + "img": left_img_path, + "nodata": "NaN", + }, + "right": { + "img": right_img_path, + }, + "col_disparity": [-2, 2], + "row_disparity": [-2, 2], + } + } + + +@pytest.fixture +def false_input_path_image(right_img_path): + return { + "input": { + "left": { + "img": "./tests/data/lt.png", + "nodata": "NaN", + }, + "right": { + "img": right_img_path, + }, + "col_disparity": [-2, 2], + "row_disparity": [-2, 2], + } + } + + +@pytest.fixture +def false_input_disp(left_img_path, right_img_path): + return { + "input": { + "left": { + "img": left_img_path, + }, + "right": { + "img": right_img_path, + }, + "col_disparity": [7, 2], + "row_disparity": [-2, 2], + } + } + + +@pytest.fixture(name="correct_pipeline") +def correct_pipeline_fixture(): + return { + "pipeline": { + "matching_cost": {"matching_cost_method": "zncc", "window_size": 5}, + "disparity": {"disparity_method": "wta", "invalid_disparity": -99}, + "refinement": {"refinement_method": "interpolation"}, + } + } + + +@pytest.fixture +def false_pipeline_mc(): + return { + "pipeline": { + "disparity": {"disparity_method": "wta", "invalid_disparity": -99}, + "refinement": {"refinement_method": "interpolation"}, + } + } + + +@pytest.fixture +def false_pipeline_disp(): + return { + "pipeline": { + "matching_cost": {"matching_cost_method": "zncc", "window_size": 5}, + "refinement": {"refinement_method": "interpolation"}, + } + } + + +@pytest.fixture +def correct_roi_sensor(): + return { + "ROI": { + "col": {"first": 10, "last": 100}, + "row": {"first": 10, "last": 100}, + } + } + + +@pytest.fixture +def false_roi_sensor_negative(): + return { + "ROI": { + "col": {"first": -10, "last": 100}, + "row": {"first": 10, "last": 100}, + } + } + + +@pytest.fixture +def false_roi_sensor_first_superior_to_last(): + return { + "ROI": { + "col": {"first": 110, "last": 100}, + "row": {"first": 10, "last": 100}, + } + } diff --git a/tests/test_check_configuration.py b/tests/unit_tests/test_check_configuration.py similarity index 68% rename from tests/test_check_configuration.py rename to tests/unit_tests/test_check_configuration.py index 60f0bc2..6e5c4e3 100644 --- a/tests/test_check_configuration.py +++ b/tests/unit_tests/test_check_configuration.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf8 # -# Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). # # This file is part of PANDORA2D # @@ -32,18 +32,17 @@ from pandora2d.img_tools import create_datasets_from_inputs, add_disparity_grid from pandora2d import check_configuration -from tests import common class TestCheckDatasets: """Test check_datasets function.""" @pytest.fixture() - def datasets(self): + def datasets(self, left_img_path, right_img_path): """Build dataset.""" input_cfg = { - "left": {"img": "./tests/data/left.png", "nodata": -9999}, - "right": {"img": "./tests/data/right.png", "nodata": -9999}, + "left": {"img": left_img_path, "nodata": -9999}, + "right": {"img": right_img_path, "nodata": -9999}, "col_disparity": [-2, 2], "row_disparity": [-3, 3], } @@ -115,71 +114,73 @@ class TestCheckInputSection: Test check input section. """ - def test_check_nominal_case(self) -> None: - assert check_configuration.check_input_section(common.correct_input) + def test_check_nominal_case(self, correct_input_cfg) -> None: + assert check_configuration.check_input_section(correct_input_cfg) - def test_false_input_disp_should_exit(self): + def test_false_input_disp_should_exit(self, false_input_disp): with pytest.raises(ValueError, match="disp_max must be bigger than disp_min"): - check_configuration.check_input_section(common.false_input_disp) + check_configuration.check_input_section(false_input_disp) - def test_false_input_path_image_should_raise_error(self): + def test_false_input_path_image_should_raise_error(self, false_input_path_image): with pytest.raises(DictCheckerError): - check_configuration.check_input_section(common.false_input_path_image) + check_configuration.check_input_section(false_input_path_image) class TestCheckPipelineSection: """Test check_pipeline_section.""" - def test_nominal_case(self, pandora2d_machine) -> None: + def test_nominal_case(self, pandora2d_machine, correct_pipeline) -> None: """ Test function for checking user pipeline section """ - assert check_configuration.check_pipeline_section(common.correct_pipeline, pandora2d_machine) + assert check_configuration.check_pipeline_section(correct_pipeline, pandora2d_machine) - def test_false_mc_dict_should_raise_error(self, pandora2d_machine): + def test_false_mc_dict_should_raise_error(self, pandora2d_machine, false_pipeline_mc): with pytest.raises(transitions.core.MachineError): - check_configuration.check_pipeline_section(common.false_pipeline_mc, pandora2d_machine) + check_configuration.check_pipeline_section(false_pipeline_mc, pandora2d_machine) - def test_false_disp_dict_should_raise_error(self, pandora2d_machine): + def test_false_disp_dict_should_raise_error(self, pandora2d_machine, false_pipeline_disp): with pytest.raises(transitions.core.MachineError): - check_configuration.check_pipeline_section(common.false_pipeline_disp, pandora2d_machine) + check_configuration.check_pipeline_section(false_pipeline_disp, pandora2d_machine) class TestCheckRoiSection: """Test check_roi_section.""" - def test_nominal_case(self) -> None: + def test_nominal_case(self, correct_roi_sensor) -> None: """ Test function for checking user ROI section """ # with a correct ROI check_roi_section should return nothing - assert check_configuration.check_roi_section(common.correct_ROI_sensor) + assert check_configuration.check_roi_section(correct_roi_sensor) - def test_dimension_lt_0_raises_exception(self): + def test_dimension_lt_0_raises_exception(self, false_roi_sensor_negative): with pytest.raises(BaseException): - check_configuration.check_roi_section(common.false_ROI_sensor_negative) + check_configuration.check_roi_section(false_roi_sensor_negative) - def test_first_dimension_gt_last_dimension_raises_exception(self): + def test_first_dimension_gt_last_dimension_raises_exception(self, false_roi_sensor_first_superior_to_last): with pytest.raises(BaseException): - check_configuration.check_roi_section(common.false_ROI_sensor_first_superior_to_last) + check_configuration.check_roi_section(false_roi_sensor_first_superior_to_last) -def test_get_roi_pipeline() -> None: +def test_get_roi_pipeline( + correct_roi_sensor, +) -> None: """ Test get_roi_pipeline function """ - assert common.correct_ROI_sensor == check_configuration.get_roi_config(common.correct_ROI_sensor) + assert correct_roi_sensor == check_configuration.get_roi_config(correct_roi_sensor) class TestCheckRoiCoherence: """Test check_roi_coherence.""" - def test_first_lt_last_is_ok(self) -> None: - check_configuration.check_roi_coherence(common.correct_ROI_sensor["ROI"]["col"]) + def test_first_lt_last_is_ok(self, correct_roi_sensor) -> None: + check_configuration.check_roi_coherence(correct_roi_sensor["ROI"]["col"]) - def test_first_gt_last_raises_error(self): + def test_first_gt_last_raises_error(self, false_roi_sensor_first_superior_to_last): with pytest.raises(ValueError) as exc_info: - check_configuration.check_roi_coherence(common.false_ROI_sensor_first_superior_to_last["ROI"]["col"]) + check_configuration.check_roi_coherence(false_roi_sensor_first_superior_to_last["ROI"]["col"]) assert str(exc_info.value) == 'In ROI "first" should be lower than "last" in sensor ROI' @@ -215,53 +216,47 @@ class TestCheckConfMatchingCostNodataCondition: """Test check conf for right image’s nodata.""" @pytest.fixture() - def build_configuration(self): - """Return a builder for configuration.""" - - def function(right_nodata, matching_cost_method): - return { - "input": { - "left": { - "img": "./tests/data/left.png", - "nodata": "NaN", - }, - "right": { - "img": "./tests/data/right.png", - "nodata": right_nodata, - }, - "col_disparity": [-2, 2], - "row_disparity": [-2, 2], + def configuration(self, right_nodata, matching_cost_method, left_img_path, right_img_path): + return { + "input": { + "left": { + "img": left_img_path, + "nodata": "NaN", }, - "pipeline": { - "matching_cost": {"matching_cost_method": matching_cost_method, "window_size": 1}, + "right": { + "img": right_img_path, + "nodata": right_nodata, }, - } - - return function + "col_disparity": [-2, 2], + "row_disparity": [-2, 2], + }, + "pipeline": { + "matching_cost": {"matching_cost_method": matching_cost_method, "window_size": 1}, + }, + } @pytest.mark.parametrize("right_nodata", ["NaN", 0.1, "inf", None]) @pytest.mark.parametrize("matching_cost_method", ["sad", "ssd"]) - def test_sad_or_ssd_fail_with(self, pandora2d_machine, build_configuration, matching_cost_method, right_nodata): + def test_sad_or_ssd_fail_with(self, pandora2d_machine, configuration): """Right nodata must be an integer with sad or ssd matching_cost_method.""" - configuration = build_configuration(right_nodata, matching_cost_method) with pytest.raises((ValueError, DictCheckerError)): check_configuration.check_conf(configuration, pandora2d_machine) + @pytest.mark.parametrize("right_nodata", [432]) @pytest.mark.parametrize("matching_cost_method", ["sad", "ssd", "zncc"]) - def test_passes_with_int(self, pandora2d_machine, build_configuration, matching_cost_method): + def test_passes_with_int(self, pandora2d_machine, configuration): """Right nodata must be an integer.""" - configuration = build_configuration(432, matching_cost_method) check_configuration.check_conf(configuration, pandora2d_machine) @pytest.mark.parametrize("right_nodata", ["NaN", "inf"]) - def test_zncc_passes_with(self, pandora2d_machine, build_configuration, right_nodata): + @pytest.mark.parametrize("matching_cost_method", ["zncc"]) + def test_zncc_passes_with(self, pandora2d_machine, configuration): """Right nodata can be inf or nan with zncc matching_cost_method.""" - configuration = build_configuration(right_nodata, "zncc") check_configuration.check_conf(configuration, pandora2d_machine) @pytest.mark.parametrize("right_nodata", [0.2, None]) - def test_zncc_fails_with(self, pandora2d_machine, build_configuration, right_nodata): + @pytest.mark.parametrize("matching_cost_method", ["zncc"]) + def test_zncc_fails_with(self, pandora2d_machine, configuration): """Right nodata must can not be float or nan with zncc matching_cost_method.""" - configuration = build_configuration(right_nodata, "zncc") with pytest.raises((ValueError, DictCheckerError)): check_configuration.check_conf(configuration, pandora2d_machine) diff --git a/tests/test_common.py b/tests/unit_tests/test_common.py similarity index 97% rename from tests/test_common.py rename to tests/unit_tests/test_common.py index 17b7783..322e58d 100644 --- a/tests/test_common.py +++ b/tests/unit_tests/test_common.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf8 # -# Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). # Copyright (c) 2024 CS GROUP France # # This file is part of PANDORA2D diff --git a/tests/test_dichotomy.py b/tests/unit_tests/test_dichotomy.py similarity index 100% rename from tests/test_dichotomy.py rename to tests/unit_tests/test_dichotomy.py diff --git a/tests/test_disparity.py b/tests/unit_tests/test_disparity.py similarity index 99% rename from tests/test_disparity.py rename to tests/unit_tests/test_disparity.py index 4951db3..e30bfe0 100644 --- a/tests/test_disparity.py +++ b/tests/unit_tests/test_disparity.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf8 # -# Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). # # This file is part of PANDORA2D # diff --git a/tests/test_estimation.py b/tests/unit_tests/test_estimation.py similarity index 100% rename from tests/test_estimation.py rename to tests/unit_tests/test_estimation.py diff --git a/tests/unit_tests/test_img_tools/__init__.py b/tests/unit_tests/test_img_tools/__init__.py new file mode 100644 index 0000000..7d10aad --- /dev/null +++ b/tests/unit_tests/test_img_tools/__init__.py @@ -0,0 +1,18 @@ +# Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). +# +# This file is part of PANDORA2D +# +# https://github.com/CNES/Pandora2D +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/tests/test_img_tools/test_create_datasets_from_input.py b/tests/unit_tests/test_img_tools/test_create_datasets_from_input.py similarity index 91% rename from tests/test_img_tools/test_create_datasets_from_input.py rename to tests/unit_tests/test_img_tools/test_create_datasets_from_input.py index 00c92f8..2b7b33f 100644 --- a/tests/test_img_tools/test_create_datasets_from_input.py +++ b/tests/unit_tests/test_img_tools/test_create_datasets_from_input.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). # Copyright (c) 2024 CS GROUP France # # This file is part of PANDORA2D @@ -33,15 +33,15 @@ from pandora2d import img_tools -def _make_input_section(): +def _make_input_section(left_img_path, right_img_path): """This is not a fixture because we want to use it with different scopes.""" return { "left": { - "img": "./tests/data/left.png", + "img": left_img_path, "nodata": -9999, }, "right": { - "img": "./tests/data/right.png", + "img": right_img_path, "nodata": -9999, }, "col_disparity": [-2, 2], @@ -50,16 +50,16 @@ def _make_input_section(): @pytest.fixture() -def input_section(): - return _make_input_section() +def input_section(left_img_path, right_img_path): + return _make_input_section(left_img_path, right_img_path) class TestReturnedValue: """Test expected properties of returned value of create_datasets_from_inputs.""" - @pytest.fixture(scope="class") - def result(self): - return img_tools.create_datasets_from_inputs(_make_input_section()) + @pytest.fixture() + def result(self, left_img_path, right_img_path): + return img_tools.create_datasets_from_inputs(_make_input_section(left_img_path, right_img_path)) def test_use_function_from_pandora(self, mocker, input_section): """Test we use `create_datset_from_inputs` from pandora. @@ -78,17 +78,17 @@ def test_use_function_from_pandora(self, mocker, input_section): any_order=True, ) - def test_returns_left_and_right_datasets(self, result): + def test_returns_left_and_right_datasets(self, result, left_img_path, right_img_path): """Test left and right datasets are returned as namedtuple.""" assert len(result) == 2 assert all(isinstance(element, xr.Dataset) for element in result) np.testing.assert_equal( result.left["im"].data, - pandora.img_tools.rasterio_open("./tests/data/left.png").read(1, out_dtype=np.float32), + pandora.img_tools.rasterio_open(left_img_path).read(1, out_dtype=np.float32), ) np.testing.assert_equal( result.right["im"].data, - pandora.img_tools.rasterio_open("./tests/data/right.png").read(1, out_dtype=np.float32), + pandora.img_tools.rasterio_open(right_img_path).read(1, out_dtype=np.float32), ) def test_disp_band_coordinates(self, result): diff --git a/tests/test_img_tools/test_get_roi_processing.py b/tests/unit_tests/test_img_tools/test_get_roi_processing.py similarity index 96% rename from tests/test_img_tools/test_get_roi_processing.py rename to tests/unit_tests/test_img_tools/test_get_roi_processing.py index d6df949..5f95b6f 100644 --- a/tests/test_img_tools/test_get_roi_processing.py +++ b/tests/unit_tests/test_img_tools/test_get_roi_processing.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). # # This file is part of PANDORA2D # diff --git a/tests/test_img_tools/test_shift_img_pandora2d.py b/tests/unit_tests/test_img_tools/test_shift_img_pandora2d.py similarity index 98% rename from tests/test_img_tools/test_shift_img_pandora2d.py rename to tests/unit_tests/test_img_tools/test_shift_img_pandora2d.py index 881dc52..f113ec7 100644 --- a/tests/test_img_tools/test_shift_img_pandora2d.py +++ b/tests/unit_tests/test_img_tools/test_shift_img_pandora2d.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). # # This file is part of PANDORA2D # diff --git a/tests/test_matching_cost.py b/tests/unit_tests/test_matching_cost.py similarity index 99% rename from tests/test_matching_cost.py rename to tests/unit_tests/test_matching_cost.py index ae19089..68577eb 100644 --- a/tests/test_matching_cost.py +++ b/tests/unit_tests/test_matching_cost.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf8 # -# Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). # Copyright (c) 2024 CS GROUP France # # This file is part of PANDORA2D diff --git a/tests/test_pandora2d.py b/tests/unit_tests/test_pandora2d.py similarity index 87% rename from tests/test_pandora2d.py rename to tests/unit_tests/test_pandora2d.py index e6fc596..5f22f78 100644 --- a/tests/test_pandora2d.py +++ b/tests/unit_tests/test_pandora2d.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf8 # -# Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). # Copyright (c) 2024 CS GROUP France # # This file is part of PANDORA2D @@ -33,7 +33,6 @@ from transitions.core import MachineError from pandora.margins import Margins -from tests import common from pandora2d import state_machine from pandora2d.img_tools import create_datasets_from_inputs @@ -44,32 +43,32 @@ class TestPandora2D: """ @staticmethod - def test_run_pandora() -> None: + def test_run_pandora(correct_pipeline, false_pipeline_mc, false_pipeline_disp) -> None: """ Test function for checking user input section """ pandora2d_machine = state_machine.Pandora2DMachine() - correct_cfg = copy.deepcopy(common.correct_pipeline) + correct_cfg = copy.deepcopy(correct_pipeline) pandora2d_machine.check_conf(correct_cfg) - false_cfg_mc = copy.deepcopy(common.false_pipeline_mc) - false_cfg_disp = copy.deepcopy(common.false_pipeline_disp) + false_cfg_mc = copy.deepcopy(false_pipeline_mc) + false_cfg_disp = copy.deepcopy(false_pipeline_disp) with pytest.raises(MachineError): pandora2d_machine.check_conf(false_cfg_mc) pandora2d_machine.check_conf(false_cfg_disp) @staticmethod - def test_run_prepare() -> None: + def test_run_prepare(left_img_path, right_img_path) -> None: """ Test run_prepare function """ pandora2d_machine = state_machine.Pandora2DMachine() input_config = { - "left": {"img": "./tests/data/left.png", "nodata": -9999}, - "right": {"img": "./tests/data/right.png", "nodata": -9999}, + "left": {"img": left_img_path, "nodata": -9999}, + "right": {"img": right_img_path, "nodata": -9999}, "col_disparity": [-2, 2], "row_disparity": [-2, 2], } diff --git a/tests/test_refinement.py b/tests/unit_tests/test_refinement.py similarity index 99% rename from tests/test_refinement.py rename to tests/unit_tests/test_refinement.py index 8d6fc68..6981274 100644 --- a/tests/test_refinement.py +++ b/tests/unit_tests/test_refinement.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2021 Centre National d'Etudes Spatiales (CNES). +# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES). # Copyright (c) 2024 CS GROUP France # # This file is part of PANDORA2D