diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e7f8a0..53c2192 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,6 @@ jobs: - "3.11" - "3.10" - "3.9" - - "3.8" os: - ubuntu-latest - macos-latest diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e4d437d..4edd8e1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,16 +68,44 @@ $ source .venv/bin/activate $ pip install -e .[dev] ``` -### Running the test +### About the tests -See README.md in the tests folder. +Tests are organized based on the structure of the [OpenAPI](https://data.oceannetworks.ca/OpenAPI) page. +Test files are named based on the API end point. +For example, `/location/tree` is tested in the test_location_tree.py file under discover_locations directory. + +Before running the tests, create a `.env` file under the root directory and put TOKEN variable in the file. +If you are on Windows, make sure the encoding of `.env` file is UTF-8 after using the command below. + +```shell +echo TOKEN=${YOUR_TOKEN} > .env +``` + +The default testing environment is PROD. If you are an internal developer, +add the following line to `.env` so that the tests are running against QA environment. + +```shell +echo ONC_ENV=QA >> .env +``` + +If testing in PROD is desired, change ONC_ENV value from QA to PROD, or simply removing the line. + +To run all tests, run + +```shell +$ pytest # or pytest --cov=onc to get a coverage report +``` Or use tox ```shell -$ tox -e py310 # py38, py39, py311, py312. Make sure the specified python version is installed. +$ tox -e py310 # py39, py311, py312. Make sure the specified python version is installed. ``` +To run specific tests, refer to [how to invoke pytest](https://docs.pytest.org/en/stable/how-to/usage.html#specifying-which-tests-to-run). +You can also use the built-in testing support of IDEs like [VS Code](https://code.visualstudio.com/docs/python/testing#_run-tests) +or [PyCharm](https://www.jetbrains.com/help/pycharm/pytest.html#run-pytest-test). + ### Formatter Code is formatted using [black](https://black.readthedocs.io/en/stable/) and [isort](https://pycqa.github.io/isort/). @@ -135,7 +163,6 @@ The actual tox environments to run are specified in the [[gh]](https://github.co ``` [gh] python = - 3.8 = py38 3.9 = py39 3.10 = py310, format-check, lint 3.11 = py311 @@ -144,7 +171,6 @@ python = In the config above, tox will run different set of tox environments on different python versions. -- on Python 3.8 job, tox runs `py38` environment, - on Python 3.9 job, tox runs `py39` environment, - on Python 3.10 job, tox runs `py310`, `format-check` and `lint` environments, - on Python 3.11 job, tox runs `py311` environment, diff --git a/pyproject.toml b/pyproject.toml index c555988..eca47b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,10 +8,10 @@ version = "2.3.5" description = "Ocean 3.0 API Python Client Library" readme = "README.md" authors = [ - { name="ONC Data Team", email="data@oceannetworks.ca" }, + { name = "ONC Data Team", email = "data@oceannetworks.ca" }, ] -license = {file = 'LICENSE.txt'} -requires-python = ">=3.8" +license = { file = 'LICENSE.txt' } +requires-python = ">=3.9" dependencies = [ "requests", 'python-dateutil', @@ -33,14 +33,13 @@ Source = "https://github.com/OceanNetworksCanada/api-python-client" [project.optional-dependencies] dev = [ - "robotframework-pabot", "ipykernel", - "robotframework", "python-dotenv", "tox", "black", "isort", "pytest", + "pytest-cov", "ruff", ] @@ -51,14 +50,11 @@ src_paths = ["onc", "tests"] [tool.ruff] # Reference for the rules https://docs.astral.sh/ruff/rules/ select = [ - "E", "W", # pycodestyle - "F", # pyflakes - "UP", # pyupgrade - "B", # flake8-bugbear - "SIM", # flake8-simplify -] -exclude = [ - "tests/robot", + "E", "W", # pycodestyle + "F", # pyflakes + "UP", # pyupgrade + "B", # flake8-bugbear + "SIM", # flake8-simplify ] [tool.pytest.ini_options] diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index 8caaaa7..0000000 --- a/tests/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# Testing Documentation - -This directory contains an automated test suite written for the Python API client using -the [Robot Framework](http://robotframework.org) (RF from now on) as well as pytest. - -Directory structure is as follows: - -- libraries: Python 3 library files used in the tests -- output: Default output directory for methods that download files (i.e. orderDataProduct()) -- pytests: Tests converted from RF to pytest format -- resources: Robot generic scripts to be reused by tests -- suites: Test suites - -Read the test suites (.robot files) in "suites" to understand what exactly is being tested. -Test suites contain the test cases in the "Test Cases" section, and are written in a language similar to english. - -## Testing Requirements - -1. Make sure Python 3 and pip are installed properly. It is highly suggested to use a virtual environment. -2. Install [Robot Framework](https://robotframework.org/) and [python-dotenv](https://saurabh-kumar.com/python-dotenv/) - -```shell -pip install robotframework python-dotenv -``` - -(or use "pip3" depending on your system configuration) - -3. Optional: install [pabot](https://pabot.org/) for test parallelization: - -```shell -pip install -U robotframework-pabot -``` - -4. Install this project in editable mode (assume the current directory is the root) - -```shell -pip install -e . -``` - -## Running the Tests - -In the terminal, run all tests from the root directory. -Tests can also be run from a different folder. Just change the relative path of the test suites. - -Create a `.env` file under tests folder and put TOKEN variable in the file. -If you are on Windows, make sure the encoding of `.env` file is UTF-8 after using the command below. - -```shell -echo TOKEN=${YOUR_TOKEN} > .env -``` - -The default testing environment is PROD. If you are an internal developer, add the following line to .env so that the tests are running against QA. - -```shell -echo ONC_ENV=QA >> .env -``` - -Change ONC_ENV value from QA to PROD if testing in PROD is needed. Removing the line also does the trick. - -_To run all the RF test suites (parallelized):_ - -```shell -pabot --testlevelsplit tests/robot/suites -``` - -_To run a single RF test suite (replace 0X with the prefix of the test file name, e.g., 01):_ - -```shell -robot tests/robot/suites/01* # robot tests/robot/suites/0X* -``` - -_To run a single RF test in a test suite (replace Y with the prefix of the test name, e.g., 01):_ - -```shell -robot --test "01*" tests/robot/suites/01* # robot --test "Y*" tests/robot/suites/0X* -``` - -_To run pytest_ - -```shell -pytest -``` - -_`--variable TOKEN:${YOUR_TOKEN}` can be used if no `.env` file is present_ - -```shell -robot --variable TOKEN:${YOUR_TOKEN} tests/robot/suites/01* -``` - -Additionally, You can check the three bash files (testall, testcoverage and testsuite) for running the test suites. -Robot Framework also has plugins for IDEs like VS Code and Pycharm that makes running tests easier. - -After tests finish, review the summary and logs in the root directory. - -## Developing Tests - -Tests are written in "almost" plain English. This is intentional to keep tests easy to read and maintain. - -If it's only required to modify a test parameter value, or just duplicating an existing test, -just make the required changes, no coding knowledge is required. - -For anything more advanced than that, please read the Robot Framework Documentation and consider keeping -the directory structure relevant. - -## Code Documentation - -Robot Framework promotes test cases written almost in plain english (if you need to document it, you're writing it wrong). -Still, code documentation is welcome if ever required. -If you are an internal user of Ocean Networks Canada, please refer to the [internal documentation page](https://internal.oceannetworks.ca/display/ONCData/11+-+Automated+User+Tests+for+API+Client+Libraries). - -## Acknowledgements - -Initial author: Dany Cabrera - -Maintainers: Kan Fu - -Previous maintainers: Dany Cabrera diff --git a/tests/archive_file/conftest.py b/tests/archive_file/conftest.py new file mode 100644 index 0000000..dba05d7 --- /dev/null +++ b/tests/archive_file/conftest.py @@ -0,0 +1,20 @@ +import pytest + + +@pytest.fixture +def params_location(): + return { + "locationCode": "NCBC", + "deviceCategoryCode": "BPR", + "dateFrom": "2019-11-23", + "dateTo": "2019-11-26", + "fileExtension": "txt", + "rowLimit": 80000, + "page": 1, + } + + +@pytest.fixture +def params_location_multiple_pages(params_location): + # rowLimit should be less than the total number of rows. + return params_location | {"rowLimit": 2} diff --git a/tests/archive_file/test_archivefile_device.py b/tests/archive_file/test_archivefile_device.py new file mode 100644 index 0000000..acea89d --- /dev/null +++ b/tests/archive_file/test_archivefile_device.py @@ -0,0 +1,72 @@ +import pytest +import requests + + +@pytest.fixture +def params(): + return { + "deviceCode": "BPR-Folger-59", + "dateFrom": "2019-11-23", + "dateTo": "2019-11-26", + "fileExtension": "txt", + "rowLimit": 80000, + "page": 1, + } + + +@pytest.fixture +def params_multiple_pages(params): + # rowLimit should be less than the total number of rows. + return params | {"rowLimit": 2} + + +def test_invalid_param_value(requester, params): + params_invalid_param_value = params | {"deviceCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getListByDevice(params_invalid_param_value) + + +def test_invalid_params_missing_required(requester, params): + del params["deviceCode"] + with pytest.raises(requests.HTTPError, match=r"API Error 128"): + requester.getListByDevice(params) + + +def test_invalid_param_name(requester, params): + params_invalid_param_name = params | {"deviceCodes": "BPR-Folger-59"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getListByDevice(params_invalid_param_name) + + +def test_no_data(requester, params): + params_no_data = params | {"dateFrom": "2000-01-01", "dateTo": "2000-01-02"} + data = requester.getListByDevice(params_no_data) + + assert len(data["files"]) == 0 + + +def test_valid_params_one_page(requester, params, params_multiple_pages): + data = requester.getListByDevice(params) + data_all_pages = requester.getListByDevice(params_multiple_pages, allPages=True) + + assert ( + len(data["files"]) > params_multiple_pages["rowLimit"] + ), "Test should return at least `rowLimit` rows." + + assert data["next"] is None, "Test should return only one page." + + assert ( + data_all_pages["files"] == data["files"] + ), "Test should concatenate rows for all pages." + + assert data_all_pages["next"] is None, "Test should return only one page." + + +def test_valid_params_multiple_pages(requester, params_multiple_pages): + data = requester.getListByDevice(params_multiple_pages) + + assert ( + len(data["files"]) == params_multiple_pages["rowLimit"] + ), "Test should only return `rowLimit` rows." + + assert data["next"] is not None, "Test should return multiple pages." diff --git a/tests/archive_file/test_archivefile_direct_download.py b/tests/archive_file/test_archivefile_direct_download.py new file mode 100644 index 0000000..8dbbf48 --- /dev/null +++ b/tests/archive_file/test_archivefile_direct_download.py @@ -0,0 +1,18 @@ +def test_valid_params_one_page(requester, params_location, util): + data = requester.getListByLocation(params_location) + result = requester.getDirectFiles(params_location) + + assert util.get_download_files_num(requester) == len(data["files"]) + + assert result["stats"]["fileCount"] == len(data["files"]) + + +def test_valid_params_multiple_pages(requester, params_location_multiple_pages, util): + result = requester.getDirectFiles(params_location_multiple_pages) + + assert ( + util.get_download_files_num(requester) + == params_location_multiple_pages["rowLimit"] + ) + + assert result["stats"]["fileCount"] == params_location_multiple_pages["rowLimit"] diff --git a/tests/archive_file/test_archivefile_download.py b/tests/archive_file/test_archivefile_download.py new file mode 100644 index 0000000..fb38bb6 --- /dev/null +++ b/tests/archive_file/test_archivefile_download.py @@ -0,0 +1,27 @@ +import pytest +import requests + + +def test_invalid_param_value(requester): + with pytest.raises(requests.HTTPError, match=r"API Error 96"): + requester.getFile("FAKEFILE.XYZ") + + +def test_invalid_params_missing_required(requester): + with pytest.raises(requests.HTTPError, match=r"API Error 128"): + requester.getFile() + + +def test_valid_params(requester, util): + filename = "BPR-Folger-59_20191123T000000.000Z.txt" + + requester.getFile(filename) + + assert (requester.outPath / filename).exists() + + with pytest.raises(FileExistsError): + requester.getFile(filename) + + requester.getFile(filename, overwrite=True) + + assert util.get_download_files_num(requester) == 1 diff --git a/tests/archive_file/test_archivefile_location.py b/tests/archive_file/test_archivefile_location.py new file mode 100644 index 0000000..4bd66d0 --- /dev/null +++ b/tests/archive_file/test_archivefile_location.py @@ -0,0 +1,60 @@ +import pytest +import requests + + +def test_invalid_param_value(requester, params_location): + params_invalid_param_value = params_location | {"locationCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getListByLocation(params_invalid_param_value) + + +def test_invalid_params_missing_required(requester, params_location): + del params_location["locationCode"] + with pytest.raises(requests.HTTPError, match=r"API Error 128"): + requester.getListByLocation(params_location) + + +def test_invalid_param_name(requester, params_location): + params_invalid_param_name = params_location | {"locationCodes": "NCBC"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getListByLocation(params_invalid_param_name) + + +def test_no_data(requester, params_location): + params_no_data = params_location | { + "dateFrom": "2000-01-01", + "dateTo": "2000-01-02", + } + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getListByLocation(params_no_data) + + +def test_valid_params_one_page( + requester, params_location, params_location_multiple_pages +): + data = requester.getListByLocation(params_location) + data_all_pages = requester.getListByLocation( + params_location_multiple_pages, allPages=True + ) + + assert ( + len(data["files"]) > params_location_multiple_pages["rowLimit"] + ), "Test should return at least `rowLimit` rows." + + assert data["next"] is None, "Test should return only one page." + + assert ( + data_all_pages["files"] == data["files"] + ), "Test should concatenate rows for all pages." + + assert data_all_pages["next"] is None, "Test should return only one page." + + +def test_valid_params_multiple_pages(requester, params_location_multiple_pages): + data = requester.getListByLocation(params_location_multiple_pages) + + assert ( + len(data["files"]) == params_location_multiple_pages["rowLimit"] + ), "Test should only return `rowLimit` rows." + + assert data["next"] is not None, "Test should return multiple pages." diff --git a/tests/conftest.py b/tests/conftest.py index edf9056..7006125 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,6 +9,31 @@ is_prod = os.getenv("ONC_ENV", "PROD") == "PROD" +def pytest_configure(): + print("========== ONC config ==========") + print(f"Testing environment: {'PROD' if is_prod else 'QA'}") + + @pytest.fixture def requester(tmp_path) -> ONC: return ONC(token, is_prod, outPath=tmp_path) + + +@pytest.fixture(scope="session") +def util(): + return Util + + +class Util: + @staticmethod + def get_download_files_num(onc: ONC) -> int: + return len(list(onc.outPath.iterdir())) + + @staticmethod + def assert_dict_key_types(data: dict, expected_keys: dict) -> None: + for key, val_type in expected_keys.items(): + assert key in data + if val_type is None: + assert data[key] is None + else: + assert isinstance(data[key], val_type) diff --git a/tests/data_product_delivery/conftest.py b/tests/data_product_delivery/conftest.py new file mode 100644 index 0000000..dd36980 --- /dev/null +++ b/tests/data_product_delivery/conftest.py @@ -0,0 +1,15 @@ +import pytest + + +@pytest.fixture() +def params() -> dict: + return { + "dataProductCode": "TSSP", + "extension": "png", + "dateFrom": "2019-08-29", + "dateTo": "2019-08-30", + "locationCode": "CRIP.C1", + "deviceCategoryCode": "CTD", + "dpo_qualityControl": 1, + "dpo_resample": "none", + } diff --git a/tests/data_product_delivery/test_data_product_delivery_download.py b/tests/data_product_delivery/test_data_product_delivery_download.py new file mode 100644 index 0000000..faacce4 --- /dev/null +++ b/tests/data_product_delivery/test_data_product_delivery_download.py @@ -0,0 +1,7 @@ +import pytest +import requests + + +def test_invalid_run_id(requester): + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.downloadDataProduct(1234567890) diff --git a/tests/data_product_delivery/test_data_product_delivery_order.py b/tests/data_product_delivery/test_data_product_delivery_order.py new file mode 100644 index 0000000..348305a --- /dev/null +++ b/tests/data_product_delivery/test_data_product_delivery_order.py @@ -0,0 +1,107 @@ +import pytest +import requests + + +@pytest.fixture() +def expected_keys_download_results() -> dict: + return { + "url": str, + "status": str, + "size": int, + "file": str, + "index": str, + "downloaded": bool, + "requestCount": int, + "fileDownloadTime": float, + } + + +def test_invalid_param_value(requester, params): + params_invalid_param_value = params | {"dataProductCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.orderDataProduct(params_invalid_param_value) + + +def test_valid_default(requester, params, expected_keys_download_results, util): + data = requester.orderDataProduct(params) + + assert ( + len(data["downloadResults"]) == 3 + ), "The first two are png files, and the third one is the metadata." + + assert data["downloadResults"][0]["status"] == "complete" + assert data["downloadResults"][0]["index"] == "1" + assert data["downloadResults"][0]["downloaded"] is True + + assert data["downloadResults"][2]["status"] == "complete" + assert data["downloadResults"][2]["index"] == "meta" + assert data["downloadResults"][2]["downloaded"] is True + + assert util.get_download_files_num(requester) == 3 + + util.assert_dict_key_types( + data["downloadResults"][0], expected_keys_download_results + ) + + +def test_valid_no_metadata(requester, params, expected_keys_download_results, util): + data = requester.orderDataProduct(params, includeMetadataFile=False) + + # The first two are png files + assert len(data["downloadResults"]) == 2 + + assert data["downloadResults"][0]["status"] == "complete" + assert data["downloadResults"][0]["index"] == "1" + assert data["downloadResults"][0]["downloaded"] is True + + assert util.get_download_files_num(requester) == 2, "The first two are png files." + + util.assert_dict_key_types( + data["downloadResults"][0], expected_keys_download_results + ) + + +def test_valid_results_only(requester, params, expected_keys_download_results, util): + data = requester.orderDataProduct(params, downloadResultsOnly=True) + + assert ( + len(data["downloadResults"]) == 3 + ), "The first two are png files, and the third one is the metadata." + + assert data["downloadResults"][0]["status"] == "complete" + assert data["downloadResults"][0]["index"] == "1" + assert data["downloadResults"][0]["downloaded"] is False + + assert data["downloadResults"][2]["status"] == "complete" + assert data["downloadResults"][2]["index"] == "meta" + assert data["downloadResults"][2]["downloaded"] is False + + assert ( + util.get_download_files_num(requester) == 0 + ), "No files should be downloaded when download_results_only is True." + + util.assert_dict_key_types( + data["downloadResults"][0], expected_keys_download_results + ) + + +def test_valid_manual(requester, params, expected_keys_download_results, util): + request_id = requester.requestDataProduct(params)["dpRequestId"] + run_id = requester.runDataProduct(request_id)["runIds"][0] + data = requester.downloadDataProduct(run_id) + + assert ( + len(data) == 3 + ), "The first two are png files, and the third one is the metadata." + + assert data[0]["status"] == "complete" + assert data[0]["index"] == "1" + assert data[0]["downloaded"] is True + + assert data[2]["status"] == "complete" + assert data[2]["index"] == "meta" + assert data[2]["downloaded"] is True + + assert util.get_download_files_num(requester) == 3 + + util.assert_dict_key_types(data[0], expected_keys_download_results) diff --git a/tests/data_product_delivery/test_data_product_delivery_run.py b/tests/data_product_delivery/test_data_product_delivery_run.py new file mode 100644 index 0000000..76463c1 --- /dev/null +++ b/tests/data_product_delivery/test_data_product_delivery_run.py @@ -0,0 +1,7 @@ +import pytest +import requests + + +def test_invalid_request_id(requester): + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.runDataProduct(1234567890) diff --git a/tests/discover_data_products/test_data_products.py b/tests/discover_data_products/test_data_products.py new file mode 100644 index 0000000..6d149bc --- /dev/null +++ b/tests/discover_data_products/test_data_products.py @@ -0,0 +1,68 @@ +import pytest +import requests + + +def test_invalid_param_value(requester): + params_invalid_param_value = {"dataProductCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getDataProducts(params_invalid_param_value) + + +def test_invalid_param_name(requester): + params_invalid_param_name = {"dataProductCodes": "HSD"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getDataProducts(params_invalid_param_name) + + +def test_no_data(requester): + params_no_data = { + "dataProductCode": "HSD", + "extension": "txt", + } + + with pytest.raises(requests.HTTPError, match=r"404 Client Error"): + requester.getDataProducts(params_no_data) + + +def test_valid_params(requester, util): + params = { + "dataProductCode": "HSD", + "extension": "png", + } + expected_keys = { + "dataProductCode": str, + "dataProductName": str, + "dataProductOptions": list, + "extension": str, + "hasDeviceData": bool, + "hasPropertyData": bool, + "helpDocument": str, + } + + expected_keys_data_product_options = { + "allowableRange": dict, + "allowableValues": list, + "defaultValue": str, + "documentation": list, + "option": str, + "suboptions": None, + } + expected_keys_data_product_options_allowable_range = { + "lowerBound": str, + "onlyIntegers": bool, + "unitOfMeasure": str, + "upperBound": str, + } + + data = requester.getDataProducts(params) + + assert len(data) > 0, "Valid properties test should return at least 1 row." + + util.assert_dict_key_types(data[0], expected_keys) + util.assert_dict_key_types( + data[0]["dataProductOptions"][6], expected_keys_data_product_options + ) + util.assert_dict_key_types( + data[0]["dataProductOptions"][6]["allowableRange"], + expected_keys_data_product_options_allowable_range, + ) diff --git a/tests/discover_deployments/test_deployments.py b/tests/discover_deployments/test_deployments.py new file mode 100644 index 0000000..b984978 --- /dev/null +++ b/tests/discover_deployments/test_deployments.py @@ -0,0 +1,83 @@ +import pytest +import requests + + +def test_invalid_time_range_greater_start_time(requester): + params_invalid_time_range_greater_start_time = { + "locationCode": "BACAX", + "deviceCategoryCode": "CTD", + "dateFrom": "2020-01-01", + "dateTo": "2019-01-01", + } + with pytest.raises(requests.HTTPError, match=r"API Error 23"): + requester.getDeployments(params_invalid_time_range_greater_start_time) + + +def test_invalid_time_range_future_start_time(requester): + params_invalid_time_range_future_start_time = { + "locationCode": "BACAX", + "deviceCategoryCode": "CTD", + "dateFrom": "2050-01-01", + } + with pytest.raises(requests.HTTPError, match=r"API Error 25"): + requester.getDeployments(params_invalid_time_range_future_start_time) + + +def test_invalid_param_value(requester): + params_invalid_param_value = {"locationCode": "XYZ123", "deviceCategoryCode": "CTD"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getDeployments(params_invalid_param_value) + + +def test_invalid_param_name(requester): + params_invalid_param_name = {"locationCodes": "BACAX", "deviceCategoryCode": "CTD"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getDeployments(params_invalid_param_name) + + +def test_no_data(requester): + params_no_data = { + "locationCode": "BACAX", + "deviceCategoryCode": "CTD", + "dateTo": "1900-01-01", + } + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getDeployments(params_no_data) + + +def test_valid_params(requester, util): + params = { + "locationCode": "BACAX", + "deviceCategoryCode": "CTD", + "dateFrom": "2015-09-17", + "dateTo": "2015-09-17T13:00:00.000Z", + } + expected_keys = { + "begin": str, + "citation": dict, + "depth": float, + "deviceCategoryCode": str, + "deviceCode": str, + "end": str, + "hasDeviceData": bool, + "heading": None, + "lat": float, + "locationCode": str, + "lon": float, + "pitch": None, + "roll": None, + } + + expected_keys_citation = { + "citation": str, + "doi": str, + "landingPageUrl": str, + "queryPid": None, + } + + data = requester.getDeployments(params) + + assert len(data) > 0, "Valid deployment test should return at least 1 row." + + util.assert_dict_key_types(data[0], expected_keys) + util.assert_dict_key_types(data[0]["citation"], expected_keys_citation) diff --git a/tests/discover_device_categories/test_device_categories.py b/tests/discover_device_categories/test_device_categories.py new file mode 100644 index 0000000..45a2a0f --- /dev/null +++ b/tests/discover_device_categories/test_device_categories.py @@ -0,0 +1,54 @@ +import pytest +import requests + + +def test_invalid_param_value(requester): + params_invalid_param_value = {"deviceCategoryCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getDeviceCategories(params_invalid_param_value) + + +def test_invalid_param_name(requester): + params_invalid_param_name = {"deviceCategoryCodes": "CTD"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getDeviceCategories(params_invalid_param_name) + + +def test_no_data(requester): + params_no_data = { + "deviceCategoryCode": "CTD", + "deviceCategoryName": "Conductivity", + "description": "TemperatureXXX", + } + with pytest.raises(requests.HTTPError, match=r"404 Client Error"): + requester.getDeviceCategories(params_no_data) + + +def test_valid_params(requester, util): + params = { + "deviceCategoryCode": "CTD", + "deviceCategoryName": "Conductivity", + "description": "Temperature", + } + expected_keys = { + "cvTerm": dict, + "description": str, + "deviceCategoryCode": str, + "deviceCategoryName": str, + "hasDeviceData": bool, + "longDescription": str, + } + + expected_keys_cv_term_device_category = { + "uri": str, + "vocabulary": str, + } + + data = requester.getDeviceCategories(params) + + assert len(data) > 0, "Valid device categories test should return at least 1 row." + + util.assert_dict_key_types(data[0], expected_keys) + util.assert_dict_key_types( + data[0]["cvTerm"]["deviceCategory"][0], expected_keys_cv_term_device_category + ) diff --git a/tests/discover_devices/test_devices.py b/tests/discover_devices/test_devices.py new file mode 100644 index 0000000..96069aa --- /dev/null +++ b/tests/discover_devices/test_devices.py @@ -0,0 +1,76 @@ +import pytest +import requests + + +def test_invalid_time_range_greater_start_time(requester): + params_invalid_time_range_greater_start_time = { + "deviceCode": "BPR-Folger-59", + "dateFrom": "2020-01-01", + "dateTo": "2019-01-01", + } + with pytest.raises(requests.HTTPError, match=r"API Error 23"): + requester.getDevices(params_invalid_time_range_greater_start_time) + + +def test_invalid_time_range_future_start_time(requester): + params_invalid_time_range_future_start_time = { + "deviceCode": "BPR-Folger-59", + "dateFrom": "2050-01-01", + } + with pytest.raises(requests.HTTPError, match=r"API Error 25"): + requester.getDevices(params_invalid_time_range_future_start_time) + + +def test_invalid_param_value(requester): + params_invalid_param_value = {"deviceCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getDevices(params_invalid_param_value) + + +def test_invalid_param_name(requester): + params_invalid_param_name = {"deviceCodes": "BPR-Folger-59"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getDevices(params_invalid_param_name) + + +def test_no_data(requester): + params_no_data = {"deviceCode": "BPR-Folger-59", "dateTo": "1900-01-01"} + with pytest.raises(requests.HTTPError, match=r"404 Client Error"): + requester.getDevices(params_no_data) + + +def test_valid_params(requester, util): + params = { + "deviceCode": "BPR-Folger-59", + "dateFrom": "2005-09-17", + "dateTo": "2020-09-17", + } + expected_keys = { + "cvTerm": dict, + "dataRating": list, + "deviceCategoryCode": str, + "deviceCode": str, + "deviceId": int, + "deviceLink": str, + "deviceName": str, + "hasDeviceData": bool, + } + expected_keys_cv_term_device = { + "uri": str, + "vocabulary": str, + } + expected_keys_data_rating = { + "dateFrom": str, + "dateTo": None, + "samplePeriod": float, + "sampleSize": int, + } + data = requester.getDevices(params) + + assert len(data) > 0, "Valid devices test should return at least 1 row." + + util.assert_dict_key_types(data[0], expected_keys) + util.assert_dict_key_types( + data[0]["cvTerm"]["device"][0], expected_keys_cv_term_device + ) + util.assert_dict_key_types(data[0]["dataRating"][0], expected_keys_data_rating) diff --git a/tests/discover_locations/test_locations.py b/tests/discover_locations/test_locations.py new file mode 100644 index 0000000..2160042 --- /dev/null +++ b/tests/discover_locations/test_locations.py @@ -0,0 +1,74 @@ +import pytest +import requests + + +def test_invalid_time_range_greater_start_time(requester): + params_invalid_time_range_greater_start_time = { + "locationCode": "FGPD", + "dateFrom": "2020-01-01", + "dateTo": "2019-01-01", + } + with pytest.raises(requests.HTTPError, match=r"API Error 23"): + requester.getLocations(params_invalid_time_range_greater_start_time) + + +def test_invalid_time_range_future_start_time(requester): + params_invalid_time_range_future_start_time = { + "locationCode": "FGPD", + "dateFrom": "2050-01-01", + } + with pytest.raises(requests.HTTPError, match=r"API Error 25"): + requester.getLocations(params_invalid_time_range_future_start_time) + + +def test_invalid_param_value(requester): + params_invalid_param_value = {"locationCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getLocations(params_invalid_param_value) + + +def test_invalid_param_name(requester): + params_invalid_param_name = {"locationCodes": "FGPD"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getLocations(params_invalid_param_name) + + +def test_no_data(requester): + params_no_data = {"locationCode": "FGPD", "dateTo": "1900-01-01"} + with pytest.raises(requests.HTTPError, match=r"404 Client Error"): + requester.getLocations(params_no_data) + + +def test_valid_params(requester, util): + params = { + "locationCode": "FGPD", + "dateFrom": "2005-09-17", + "dateTo": "2020-09-17", + } + expected_keys = { + "deployments": int, + "locationName": str, + "depth": float, + "bbox": dict, + "description": str, + "hasDeviceData": bool, + "lon": float, + "locationCode": str, + "hasPropertyData": bool, + "lat": float, + "dataSearchURL": str, + } + expected_keys_bbox = { + "maxDepth": float, + "maxLat": float, + "maxLon": float, + "minDepth": float, + "minLat": float, + "minLon": float, + } + data = requester.getLocations(params) + + assert len(data) > 0, "Valid locations test should return at least 1 row." + + util.assert_dict_key_types(data[0], expected_keys) + util.assert_dict_key_types(data[0]["bbox"], expected_keys_bbox) diff --git a/tests/discover_locations/test_locations_tree.py b/tests/discover_locations/test_locations_tree.py new file mode 100644 index 0000000..17efff9 --- /dev/null +++ b/tests/discover_locations/test_locations_tree.py @@ -0,0 +1,61 @@ +import pytest +import requests + + +def test_invalid_time_range_greater_start_time(requester): + params_invalid_time_range_greater_start_time = { + "locationCode": "ARCT", + "dateFrom": "2020-01-01", + "dateTo": "2019-01-01", + } + with pytest.raises(requests.HTTPError, match=r"API Error 23"): + requester.getLocationHierarchy(params_invalid_time_range_greater_start_time) + + +def test_invalid_time_range_future_start_time(requester): + params_invalid_time_range_future_start_time = { + "locationCode": "ARCT", + "dateFrom": "2050-01-01", + } + with pytest.raises(requests.HTTPError, match=r"API Error 25"): + requester.getLocationHierarchy(params_invalid_time_range_future_start_time) + + +def test_invalid_param_value(requester): + params_invalid_param_value = {"locationCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getLocationHierarchy(params_invalid_param_value) + + +def test_invalid_param(requester): + params_invalid_param_name = {"locationCodes": "ARCT"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getLocationHierarchy(params_invalid_param_name) + + +def test_no_data(requester): + params_no_data = {"locationCode": "ARCT", "dateTo": "1900-01-01"} + with pytest.raises(requests.HTTPError, match=r"404 Client Error"): + requester.getLocationHierarchy(params_no_data) + + +def test_valid_params(requester, util): + params = {"locationCode": "ARCT", "deviceCategoryCode": "VIDEOCAM"} + expected_keys = { + "locationName": str, + "children": list, + "description": str, + "hasDeviceData": bool, + "locationCode": str, + "hasPropertyData": bool, + } + + data = requester.getLocationHierarchy(params) + + assert len(data) > 0, "Valid locations tree test should return at least 1 row." + + assert ( + len(data[0]["children"]) > 0 + ), "valid locations tree test should return at least 1 row in the children." + + util.assert_dict_key_types(data[0], expected_keys) diff --git a/tests/discover_properties/test_properties.py b/tests/discover_properties/test_properties.py new file mode 100644 index 0000000..a72d88b --- /dev/null +++ b/tests/discover_properties/test_properties.py @@ -0,0 +1,53 @@ +import pytest +import requests + + +def test_invalid_param_value(requester): + params_invalid_param_value = {"propertyCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getProperties(params_invalid_param_value) + + +def test_invalid_param_name(requester): + params_invalid_param_name = {"propertyCodes": "conductivity"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getProperties(params_invalid_param_name) + + +def test_no_data(requester): + params_no_data = { + "propertyCode": "conductivity", + "locationCode": "SAAN", + } + + with pytest.raises(requests.HTTPError, match=r"404 Client Error"): + requester.getProperties(params_no_data) + + +def test_valid_params(requester, util): + params = { + "propertyCode": "conductivity", + "locationCode": "BACAX", + "deviceCategoryCode": "CTD", + } + expected_keys = { + "cvTerm": dict, + "description": str, + "hasDeviceData": bool, + "hasPropertyData": bool, + "propertyCode": str, + "propertyName": str, + "uom": str, + } + + expected_keys_cv_term_uom = { + "uri": str, + "vocabulary": str, + } + + data = requester.getProperties(params) + + assert len(data) > 0, "Valid properties test should return at least 1 row." + + util.assert_dict_key_types(data[0], expected_keys) + util.assert_dict_key_types(data[0]["cvTerm"]["uom"][0], expected_keys_cv_term_uom) diff --git a/tests/raw_data/test_rawdata_device.py b/tests/raw_data/test_rawdata_device.py new file mode 100644 index 0000000..216abea --- /dev/null +++ b/tests/raw_data/test_rawdata_device.py @@ -0,0 +1,68 @@ +import pytest +import requests + + +@pytest.fixture +def params(): + return { + "deviceCode": "BPR-Folger-59", + "dateFrom": "2019-11-23T00:00:00.000Z", + "dateTo": "2019-11-23T00:01:00.000Z", + "rowLimit": 80000, + } + + +@pytest.fixture +def params_multiple_pages(params): + # rowLimit should be less than the total number of rows. + return params | {"rowLimit": 25} + + +def test_invalid_param_value(requester, params): + params_invalid_param_value = params | {"deviceCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getDirectByDevice(params_invalid_param_value) + + +def test_invalid_param_name(requester, params): + params_invalid_param_name = params | {"deviceCodes": "BPR-Folger-59"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getDirectByDevice(params_invalid_param_name) + + +def test_no_data(requester, params): + params_no_data = params | {"dateFrom": "2000-01-01", "dateTo": "2000-01-02"} + data = requester.getDirectByDevice(params_no_data) + + assert data["sensorData"] is None + + +def test_valid_params_one_page(requester, params, params_multiple_pages): + data = requester.getDirectByDevice(params) + data_all_pages = requester.getDirectByDevice(params_multiple_pages, allPages=True) + + assert ( + _get_row_num(data) > params_multiple_pages["rowLimit"] + ), "Test should return at least `rowLimit` rows for each sensor." + + assert data["next"] is None, "Test should return only one page." + + assert ( + data_all_pages["sensorData"][0]["data"] == data["sensorData"][0]["data"] + ), "Test should concatenate rows for all pages." + + assert data_all_pages["next"] is None, "Test should return only one page." + + +def test_valid_params_multi_pages(requester, params_multiple_pages): + data = requester.getDirectByDevice(params_multiple_pages) + + assert ( + _get_row_num(data) == params_multiple_pages["rowLimit"] + ), "Test should only return `rowLimit` rows for each sensor." + + assert data["next"] is not None, "Test should return multiple pages." + + +def _get_row_num(data): + return len(data["sensorData"][0]["data"]["values"]) diff --git a/tests/raw_data/test_rawdata_location.py b/tests/raw_data/test_rawdata_location.py new file mode 100644 index 0000000..e7cb218 --- /dev/null +++ b/tests/raw_data/test_rawdata_location.py @@ -0,0 +1,72 @@ +import pytest +import requests + + +@pytest.fixture +def params(): + return { + "locationCode": "NCBC", + "deviceCategoryCode": "BPR", + "dateFrom": "2019-11-23T00:00:00.000Z", + "dateTo": "2019-11-23T00:01:00.000Z", + "rowLimit": 80000, + "sizeLimit": 20, + "convertHexToDecimal": False, + } + + +@pytest.fixture +def params_multiple_pages(params): + # rowLimit should be less than the total number of rows. + return params | {"rowLimit": 25} + + +def test_invalid_param_value(requester, params): + params_invalid_param_value = params | {"locationCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getDirectRawByLocation(params_invalid_param_value) + + +def test_invalid_param_name(requester, params): + params_invalid_param_name = params | {"locationCodes": "NCBC"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getDirectRawByLocation(params_invalid_param_name) + + +def test_no_data(requester, params): + params_no_data = params | {"dateFrom": "2000-01-01", "dateTo": "2000-01-02"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getDirectRawByLocation(params_no_data) + + +def test_valid_params_one_page(requester, params, params_multiple_pages): + data = requester.getDirectRawByLocation(params) + data_all_pages = requester.getDirectRawByLocation( + params_multiple_pages, allPages=True + ) + + assert ( + _get_row_num(data) > params_multiple_pages["rowLimit"] + ), "Test should return at least `rowLimit` rows." + + assert data["next"] is None, "Test should return only one page." + + assert ( + data_all_pages["data"] == data["data"] + ), "Test should concatenate rows for all pages." + + assert data_all_pages["next"] is None, "Test should return only one page." + + +def test_valid_params_multiple_pages(requester, params_multiple_pages): + data = requester.getDirectRawByLocation(params_multiple_pages) + + assert ( + _get_row_num(data) == params_multiple_pages["rowLimit"] + ), "Test should only return `rowLimit` rows for each sensor." + + assert data["next"] is not None, "Test should return multiple pages." + + +def _get_row_num(data): + return len(data["data"]["readings"]) diff --git a/tests/robot/libraries/common.py b/tests/robot/libraries/common.py deleted file mode 100644 index 17bcc39..0000000 --- a/tests/robot/libraries/common.py +++ /dev/null @@ -1,107 +0,0 @@ -import json -import os - -from env_variable import is_prod, token -from expectedfields import expectedFields -from onc.onc import ONC - -onc = ONC(token, is_prod, True, "output") - - -def runMethod(name: str, filters: dict, param1=None): - """ - Runs a method from the global onc object - optionally allows for a second nameless parameter - """ - if name == "getLocations": - return onc.getLocations(filters) - elif name == "getLocationHierarchy": - return onc.getLocationHierarchy(filters) - elif name == "getDeployments": - return onc.getDeployments(filters) - elif name == "getDevices": - return onc.getDevices(filters) - elif name == "getDeviceCategories": - return onc.getDeviceCategories(filters) - elif name == "getProperties": - return onc.getProperties(filters) - elif name == "getDataProducts": - return onc.getDataProducts(filters) - elif name == "getDirectScalar": - return onc.getDirectScalar(filters, param1) - elif name == "getDirectByLocation": - return onc.getDirectByLocation(filters, param1) - elif name == "getDirectByDevice": - return onc.getDirectByDevice(filters, param1) - elif name == "getDirectRawByLocation": - return onc.getDirectRawByLocation(filters, param1) - elif name == "getDirectRawByDevice": - return onc.getDirectRawByDevice(filters, param1) - elif name == "getListByLocation": - return onc.getListByLocation(filters, param1) - elif name == "getListByDevice": - return onc.getListByDevice(filters, param1) - - -def makeOnc(token: str, outPath="output"): - # Returns a onc instance - return ONC(token, is_prod, True, outPath) - - -def dataHasExpectedFields(data, methodName): - # True if data is an element with the fields and types described in - # the expectedFields global - # False otherwise, and prints an error message as hint - expected = expectedFields[methodName] - for expectedField, expectedType in expected.items(): - # can this field be null? - canBeNull = False - if expectedType[-1] == "*": - expectedType = expectedType[:-1] - canBeNull = True - - # Is the field present? - if expectedField in data: - value = data[expectedField] - ty = type(value).__name__ - print('Type of field "{:s}" is "{:s}"'.format(expectedField, ty)) - - # Is the type as expected? - if not (canBeNull and (ty == "NoneType")): - if ty != expectedType: - print( - 'Type of field "{:s}" is "{:s}" but was expected "{:s}"'.format( - expectedField, ty, expectedType - ) - ) - return False - else: - print('Field "{:s}" not found'.format(expectedField)) - return False - return True - - -def isOncInstalled(): - """ - Returns True if the onc package is installed - """ - try: - from onc.onc import ONC - except ImportError: - return False - return True - - -def saveJsonToFile(obj: dict, filepath: str): - """ - saves a json dictionary structure to a file - tries to beautify the output - """ - # create path if it doesn't exist - path, filename = os.path.split(filepath) - if not os.path.exists(path): - os.makedirs(path) - - text = json.dumps(obj, indent=4) - with open(filepath, "w+") as file: - file.write(text) diff --git a/tests/robot/libraries/delivery.py b/tests/robot/libraries/delivery.py deleted file mode 100644 index 82ca399..0000000 --- a/tests/robot/libraries/delivery.py +++ /dev/null @@ -1,31 +0,0 @@ -# delivery services' tests - -from pathlib import Path - -from common import onc - - -def manualRequestProduct(filters: dict): - # Manually requests data product, doesn't execute or download - return onc.requestDataProduct(filters) - - -def manualRunProduct(dpRequestId: int): - # Manually runs request id - return onc.runDataProduct(dpRequestId) - - -def manualDownloadProduct(dpRunId: int, outPath: str = "", resultsOnly: bool = False): - # Manually downloads runId - onc.outPath = outPath - return onc.downloadDataProduct(dpRunId, downloadResultsOnly=resultsOnly) - - -def test_getDataProductUrls(onc, filters): - print("\n9. TEST getDataProductUrls()") - res = onc.getDataProductUrls(filters) - - -def test_downloadFile(onc, url): - print("\n9. TEST downloadFile()") - res = onc.downloadFile(url) diff --git a/tests/robot/libraries/env_variable.py b/tests/robot/libraries/env_variable.py deleted file mode 100644 index cedcbb9..0000000 --- a/tests/robot/libraries/env_variable.py +++ /dev/null @@ -1,13 +0,0 @@ -import os - -from dotenv import load_dotenv - -from robot.libraries.BuiltIn import BuiltIn, RobotNotRunningError - -load_dotenv(override=True) -try: - robot_val = BuiltIn().get_variable_value("${TOKEN}") -except RobotNotRunningError: - robot_val = None -token = os.getenv("TOKEN", robot_val) -is_prod = os.getenv("ONC_ENV", "PROD") == "PROD" diff --git a/tests/robot/libraries/expectedfields.py b/tests/robot/libraries/expectedfields.py deleted file mode 100644 index 256df1a..0000000 --- a/tests/robot/libraries/expectedfields.py +++ /dev/null @@ -1,84 +0,0 @@ -# Expected fields information for the responses the client methods return -# Note that: -# Python's float type has float precision -# Field types that end with a * can also have the None type - -expectedFields = { - "getLocations": { - "locationCode": "str", - "locationName": "str", - "description": "str", - "deployments": "int", - "hasDeviceData": "bool", - "hasPropertyData": "bool", - "bbox": "dict*", - "lon": "float*", - "lat": "float*", - "depth": "float*", - "dataSearchURL": "str", - }, - "getLocationHierarchy": { - "locationCode": "str", - "locationName": "str", - "description": "str", - "hasDeviceData": "bool", - "hasPropertyData": "bool", - "children": "list", - }, - "getDevices": { - "deviceCode": "str", - "deviceId": "int", - "deviceName": "str", - "deviceLink": "str", - "dataRating": "list", - "cvTerm": "dict", - "hasDeviceData": "bool", - }, - "getDeviceCategories": { - "deviceCategoryCode": "str", - "deviceCategoryName": "str", - "description": "str", - "hasDeviceData": "bool", - "longDescription": "str", - "cvTerm": "dict", - }, - "getDeployments": { - "begin": "str", - "depth": "float", - "deviceCode": "str", - "end": "str*", - "hasDeviceData": "bool", - "heading": "float*", - "lat": "float", - "locationCode": "str", - "lon": "float", - "pitch": "float*", - "roll": "float*", - }, - "getProperties": { - "propertyCode": "str", - "propertyName": "str", - "description": "str", - "hasDeviceData": "bool", - "hasPropertyData": "bool", - "uom": "str", - "cvTerm": "dict", - }, - "getDataProducts": { - "dataProductCode": "str", - "dataProductName": "str", - "extension": "str", - "hasDeviceData": "bool", - "hasPropertyData": "bool", - "helpDocument": "str", - }, - "orderDataProduct": { - "index": "str", - "url": "str", - "status": "str", - "downloaded": "bool", - "file": "str", - "size": "int", - "fileDownloadTime": "float", - }, -} diff --git a/tests/robot/resources/general.robot b/tests/robot/resources/general.robot deleted file mode 100644 index 5245ecd..0000000 --- a/tests/robot/resources/general.robot +++ /dev/null @@ -1,104 +0,0 @@ -*** Settings *** -Library ../libraries/common.py -Library Collections -Library OperatingSystem -Variables ../libraries/env_variable.py - -*** Variables *** -${onc} makeOnc ${token} output - -*** Keywords *** -# Object generation -Make ONC with path - [Arguments] ${path} - ${oncObj}= makeOnc ${token} ${path} - [Return] ${oncObj} - - -# Create directory if it doesn't exist, delete its contents otherwise -Prepare output directory - [Arguments] ${testPath} - ${path}= Catenate SEPARATOR= ${EXECDIR} ${/} ${testPath} - Create Directory ${path} - Empty Directory ${path} - -Downloaded ${expected} files to ${outPath} - ${count}= Count Files In Directory ${EXECDIR}${/}${outPath} - Should Be Equal As Integers ${count} ${expected} - - -# List conditions - -List ${list} has at least ${txtMin} rows - ${min}= Convert To Integer ${txtMin} - ${length}= Get length ${list} - Should Be True ${length} >= ${min} - -List ${list} has at most ${txtMax} rows - ${max}= Convert To Integer ${txtMax} - ${length}= Get length ${list} - Should Be True ${length} <= ${max} - -List ${list} has exactly ${txtNum} rows - ${n}= Convert To Integer ${txtNum} - ${length}= Get length ${list} - Should Be Equal ${length} ${n} - -List ${data} is empty - ${type} = Evaluate type($data).__name__ - Should Be Equal ${type} list - Length Should Be ${data} ${0} - -First row in ${list} has key "${name:[^"]+}" - Dictionary Should Contain Key ${list}[0] ${name} - -First row in ${list} has key "${name}" with value "${value}" - Dictionary Should Contain Key ${list}[0] ${name} - ${myValue}= Get From Dictionary ${list}[0] ${name} - Should Be Equal ${myValue} ${value} - - -# Field checks - -Elements in ${data} have the expected fields for ${methodName} - ${valid}= Data Has Expected Fields ${data} ${methodName} - Should Be True ${valid} - -Field "${fieldName}" in ${list} holds the value "${expected}" - Should Be Equal ${list}[${fieldName}] ${expected} - -Should be an error response - [Arguments] ${data} - Length Should Be ${data} ${1} - Dictionary Should Contain Key ${data}[0] errors - ${errors}= ${data}[0][errors] - Dictionary Should Contain Key ${errors} errorCode - Dictionary Should Contain Key ${errors} errorMessage - - -# Method execution - -Run method ${methodName} without filters - ${result}= Run Method ${methodName} {} - [return] ${result} - -Run method ${methodName} with filters ${filters} - ${result}= Run Method ${methodName} ${filters} - [return] ${result} - -Run method ${methodName} with ${filters} and parameter ${param1} - ${result}= Run Method ${methodName} ${filters} ${param1} - [return] ${result} - -Run method ${methodName} with filter ${filterName}="${filterValue}" - ${result}= Run Method ${methodName} {"${filterName}": "${filterValue}"} - [return] ${result} - -Method ${methodName} with filter ${filterName}="${filterValue}" returns a row with ${expectedName}="${expectedValue}" - ${result}= Run Method ${methodName} {"${filterName}": "${filterValue}"} - ${resultValue}= Get From Dictionary ${result}[0] ${expectedName} - Should Be Equal ${resultValue} ${expectedValue} - -Run method ${methodName} from "${dateFrom}" to "${dateTo}" - ${result}= Run Method ${methodName} {"dateFrom": "${dateFrom}", "dateTo": "${dateTo}"} - [return] ${result} diff --git a/tests/robot/suites/00__initial.robot b/tests/robot/suites/00__initial.robot deleted file mode 100644 index 0932e74..0000000 --- a/tests/robot/suites/00__initial.robot +++ /dev/null @@ -1,24 +0,0 @@ -# Generic tests outside the other test suites - -*** Settings *** -Documentation 00. Initialization Test Suite -Resource ../resources/general.robot - -*** Variables *** -&{F_LOCATIONCODE} locationCode=CQSBG - -*** Test Cases *** -01. ONC pip package is installed - ${isInstalled}= isOncInstalled - Should Be True ${isInstalled} - -02. Invalid token return unauthorized error - ${onc}= makeOnc FAKE_TOKEN output - Run Keyword And Expect Error *401* Call Method ${onc} getLocations ${F_LOCATIONCODE} - -03. Save arbitrary JSON to file (getLocations) - Prepare output directory output/00/03 - ${onc3}= Make ONC with path output/00/03 - ${result}= Call Method ${onc3} getLocations ${F_LOCATIONCODE} - Call Method ${onc3} print ${result} 03.json - File Should Exist output/00/03/03.json \ No newline at end of file diff --git a/tests/robot/suites/01__locations.robot b/tests/robot/suites/01__locations.robot deleted file mode 100644 index 794b02b..0000000 --- a/tests/robot/suites/01__locations.robot +++ /dev/null @@ -1,70 +0,0 @@ -*** Settings *** -Documentation 01. Locations Test Suite -Resource ../resources/general.robot - - -*** Variables *** -&{F_INCL_HILDREN}= locationCode=SAAN includeChildren=true -&{F_NO_RESULTS}= locationCode=SAAN dateTo=1995-03-24T00:00:01.000Z - - -*** Test Cases *** - -01. Get all locations - ${data}= Run method getLocations without filters - Elements in ${data}[0] have the expected fields for getLocations - List ${data} has at least 500 rows - -02. Get locations hierarchy - ${data}= Run method getLocationHierarchy with filter locationCode="SAAN" - Elements in ${data}[0] have the expected fields for getLocationHierarchy - List ${data}[0][children] has at least 2 rows - -# Single filters - -03. Filter locationCode - ${data}= Run method getLocations with filter locationCode="CQSBG" - Elements in ${data}[0] have the expected fields for getLocations - List ${data} has exactly 1 rows - Field "locationCode" in ${data}[0] holds the value "CQSBG" - -04. Filter locationName - ${data}= Run method getLocations with filter locationName="Bubbly Gulch" - Elements in ${data}[0] have the expected fields for getLocations - List ${data} has exactly 1 rows - Field "locationCode" in ${data}[0] holds the value "CQSBG" - -05. Filter deviceCategoryCode - ${data}= Run method getLocations with filter deviceCategoryCode="CTD" - Elements in ${data}[0] have the expected fields for getLocations - List ${data} has at least 50 rows - -06. Filter deviceCode - ${data}= Run method getLocations with filter deviceCode="NORTEKADCP9917" - Elements in ${data}[0] have the expected fields for getLocations - List ${data} has at least 1 rows - -07. Filter propertyCode - ${data}= Run method getLocations with filter propertyCode="co2concentration" - Elements in ${data}[0] have the expected fields for getLocations - List ${data} has at least 1 rows - -08. Filter dataProductCode - ${data}= Run method getLocations with filter dataProductCode="MP4V" - Elements in ${data}[0] have the expected fields for getLocations - List ${data} has at least 20 rows - -09. Filter includeChildren - ${data}= Run method getLocations with filters ${F_INCL_HILDREN} - Elements in ${data}[0] have the expected fields for getLocations - List ${data} has at least 30 rows - -# Other - -10. ISO Date Range - ${data}= Run method getLocations from "2014-02-24T00:00:01.000Z" to "2014-03-24T00:00:01.000Z" - Elements in ${data}[0] have the expected fields for getLocations - List ${data} has at least 100 rows - -12. No locations found - Run Keyword And Expect Error *404* Run method getLocations with filters ${F_NO_RESULTS} \ No newline at end of file diff --git a/tests/robot/suites/02__deployments.robot b/tests/robot/suites/02__deployments.robot deleted file mode 100644 index 3661545..0000000 --- a/tests/robot/suites/02__deployments.robot +++ /dev/null @@ -1,46 +0,0 @@ -*** Settings *** - -Documentation 02. Deployments Test Suite -Resource ../resources/general.robot - - -*** Variables *** - -&{F_NO_RESULTS}= locationCode=SAAN dateTo=1995-03-24T00:00:01.000Z - - -*** Test Cases *** - -# 01. Get all deployments -# ${data}= Run method getDeployments without filters -# Elements in ${data}[0] have the expected fields for getDeployments -# List ${data} has at least 500 rows - -02. Filter locationCode - [Tags] runthis - ${data}= Run method getDeployments with filter locationCode="CQSBG" - Elements in ${data}[0] have the expected fields for getDeployments - List ${data} has at least 2 rows - -03. Filter deviceCategoryCode - ${data}= Run method getDeployments with filter deviceCategoryCode="BPR" - Elements in ${data}[0] have the expected fields for getDeployments - List ${data} has at least 50 rows - -04. Filter deviceCode - ${data}= Run method getDeployments with filter deviceCode="NORTEKADCP9917" - Elements in ${data}[0] have the expected fields for getDeployments - List ${data} has at least 1 rows - -05. Filter propertyCode - ${data}= Run method getDeployments with filter propertyCode="co2concentration" - Elements in ${data}[0] have the expected fields for getDeployments - List ${data} has at least 1 rows - -06. ISO Date Range - ${data}= Run method getDeployments from "2008-02-24T00:00:01.000Z" to "2008-03-24T00:00:01.000Z" - Elements in ${data}[0] have the expected fields for getDeployments - List ${data} has at least 40 rows - -08. No deployments found - Run Keyword And Expect Error *404* Run method getDeployments with filters ${F_NO_RESULTS} \ No newline at end of file diff --git a/tests/robot/suites/03__device_categories.robot b/tests/robot/suites/03__device_categories.robot deleted file mode 100644 index cd7a7cf..0000000 --- a/tests/robot/suites/03__device_categories.robot +++ /dev/null @@ -1,47 +0,0 @@ -*** Settings *** -Documentation 03. DeviceCategories Test Suite -Resource ../resources/general.robot - - -*** Variables *** - -&{F_NO_RESULTS}= locationCode=SAAN propertyCode=co2concentration - - -*** Test Cases *** - -01. Get all deviceCategories - ${data}= Run method getDeviceCategories without filters - Elements in ${data}[0] have the expected fields for getDeviceCategories - List ${data} has at least 100 rows - -02. Filter deviceCategoryCode - ${data}= Run method getDeviceCategories with filter deviceCategoryCode="ADCP1200KHZ" - Elements in ${data}[0] have the expected fields for getDeviceCategories - List ${data} has exactly 1 rows - Field "deviceCategoryCode" in ${data}[0] holds the value "ADCP1200KHZ" - -03. Filter deviceCategoryName - ${data}= Run method getDeviceCategories with filter deviceCategoryName="Current Profiler 1200" - Elements in ${data}[0] have the expected fields for getDeviceCategories - List ${data} has exactly 1 rows - Field "deviceCategoryCode" in ${data}[0] holds the value "ADCP1200KHZ" - -04. Filter description - ${data}= Run method getDeviceCategories with filter description="3D Camera" - Elements in ${data}[0] have the expected fields for getDeviceCategories - List ${data} has exactly 1 rows - Field "deviceCategoryCode" in ${data}[0] holds the value "CAMERA_3D" - -05. Filter locationCode - ${data}= Run method getDeviceCategories with filter locationCode="CQSBG" - Elements in ${data}[0] have the expected fields for getDeviceCategories - List ${data} has at least 1 rows - -06. Filter propertyCode - ${data}= Run method getDeviceCategories with filter propertyCode="co2concentration" - Elements in ${data}[0] have the expected fields for getDeviceCategories - List ${data} has at least 1 rows - -08. No deviceCategories found - Run Keyword And Expect Error *404* Run method getDeviceCategories with filters ${F_NO_RESULTS} diff --git a/tests/robot/suites/04__devices.robot b/tests/robot/suites/04__devices.robot deleted file mode 100644 index a9dea0c..0000000 --- a/tests/robot/suites/04__devices.robot +++ /dev/null @@ -1,56 +0,0 @@ -*** Settings *** -Documentation 04. Devices Test Suite -Resource ../resources/general.robot - - -*** Variables *** - -&{F_NO_RESULTS}= locationCode=SAAN dateTo=1995-03-24T00:00:01.000Z - - -*** Test Cases *** - -01. Get all devices - ${data}= Run method getDevices without filters - Elements in ${data}[0] have the expected fields for getDevices - List ${data} has at least 300 rows - -02. Filter deviceCode - ${data}= Run method getDevices with filter deviceCode="NORTEKADCP9917" - Elements in ${data}[0] have the expected fields for getDevices - List ${data} has exactly 1 rows - Field "deviceCode" in ${data}[0] holds the value "NORTEKADCP9917" - -03. Filter deviceName - ${data}= Run method getDevices with filter deviceName="Nortek Aquadopp HR-Profiler 2 MHz 2700" - Elements in ${data}[0] have the expected fields for getDevices - List ${data} has exactly 1 rows - Field "deviceCode" in ${data}[0] holds the value "BC_POD1_AD2M" - -04. Filter locationCode - ${data}= Run method getDevices with filter locationCode="CQSBG" - Elements in ${data}[0] have the expected fields for getDevices - List ${data} has at least 1 rows - -05. Filter deviceCategoryCode - ${data}= Run method getDevices with filter deviceCategoryCode="CTD" - Elements in ${data}[0] have the expected fields for getDevices - List ${data} has at least 100 rows - -06. Filter propertyCode - ${data}= Run method getDevices with filter propertyCode="co2concentration" - Elements in ${data}[0] have the expected fields for getDevices - List ${data} has at least 2 rows - -07. Filter dataProductCode - ${data}= Run method getDevices with filter dataProductCode="MP4V" - Elements in ${data}[0] have the expected fields for getDevices - List ${data} has at least 20 rows - -08. ISO Date Range - ${data}= Run method getDevices from "2014-02-24T00:00:01.000Z" to "2014-03-24T00:00:01.000Z" - Elements in ${data}[0] have the expected fields for getDevices - List ${data} has at least 100 rows - -10. No devices found - Run Keyword And Expect Error *404* Run method getDevices with filters ${F_NO_RESULTS} diff --git a/tests/robot/suites/05__properties.robot b/tests/robot/suites/05__properties.robot deleted file mode 100644 index df2e7f9..0000000 --- a/tests/robot/suites/05__properties.robot +++ /dev/null @@ -1,52 +0,0 @@ -*** Settings *** -Documentation 05. Properties Test Suite -Resource ../resources/general.robot - - -*** Variables *** - -&{F_NO_RESULTS}= locationCode=SAAN deviceCategoryCode=POWER_SUPPLY - - -*** Test Cases *** - -01. Get all properties - ${data}= Run method getProperties without filters - Elements in ${data}[0] have the expected fields for getProperties - List ${data} has at least 150 rows - -02. Filter propertyCode - ${data}= Run method getProperties with filter propertyCode="absolutehumidity" - Elements in ${data}[0] have the expected fields for getProperties - List ${data} has exactly 1 rows - Field "propertyCode" in ${data}[0] holds the value "absolutehumidity" - -03. Filter propertyName - ${data}= Run method getProperties with filter propertyName="Bender Electrical Resistance" - Elements in ${data}[0] have the expected fields for getProperties - List ${data} has exactly 1 rows - Field "propertyCode" in ${data}[0] holds the value "benderelectricalresistance" - -04. Filter description - ${data}= Run method getProperties with filter description="Kurtosis Statistical Analysis" - Elements in ${data}[0] have the expected fields for getProperties - List ${data} has exactly 1 rows - Field "propertyCode" in ${data}[0] holds the value "kurtosisstatisticalanalysis" - -05. Filter locationCode - ${data}= Run method getProperties with filter locationCode="ROVMP" - Elements in ${data}[0] have the expected fields for getProperties - List ${data} has at least 1 rows - -06. Filter deviceCategoryCode - ${data}= Run method getProperties with filter deviceCategoryCode="CTD" - Elements in ${data}[0] have the expected fields for getProperties - List ${data} has at least 10 rows - -07. Filter deviceCode - ${data}= Run method getProperties with filter deviceCode="ALECACTW-CAR0014" - Elements in ${data}[0] have the expected fields for getProperties - List ${data} has at least 3 rows - -09. No properties found - Run Keyword And Expect Error *404* Run method getProperties with filters ${F_NO_RESULTS} \ No newline at end of file diff --git a/tests/robot/suites/06__data_product_discovery.robot b/tests/robot/suites/06__data_product_discovery.robot deleted file mode 100644 index 6c2c89b..0000000 --- a/tests/robot/suites/06__data_product_discovery.robot +++ /dev/null @@ -1,51 +0,0 @@ -*** Settings *** -Documentation 06. Data Product Discovery Test Suite -Resource ../resources/general.robot - - -*** Variables *** - -&{F_NO_RESULTS}= locationCode=SAAN deviceCategoryCode=POWER_SUPPLY - - -*** Test Cases *** - -01. Get all data products - ${data}= Run method getDataProducts without filters - Elements in ${data}[0] have the expected fields for getDataProducts - List ${data} has at least 100 rows - -02. Filter dataProductCode - ${data}= Run method getDataProducts with filter dataProductCode="CPD" - Elements in ${data}[0] have the expected fields for getDataProducts - List ${data} has exactly 1 rows - Field "dataProductCode" in ${data}[0] holds the value "CPD" - -03. Filter extension - ${data}= Run method getDataProducts with filter extension="cor" - Elements in ${data}[0] have the expected fields for getDataProducts - List ${data} has exactly 2 rows - Field "extension" in ${data}[0] holds the value "cor" - -04. Filter locationCode - ${data}= Run method getDataProducts with filter locationCode="SAAN" - Elements in ${data}[0] have the expected fields for getDataProducts - List ${data} has at least 1 rows - -05. Filter deviceCategoryCode - ${data}= Run method getDataProducts with filter deviceCategoryCode="CTD" - Elements in ${data}[0] have the expected fields for getDataProducts - List ${data} has at least 20 rows - -06. Filter deviceCode - ${data}= Run method getDataProducts with filter deviceCode="BC_POD1_AD2M" - Elements in ${data}[0] have the expected fields for getDataProducts - List ${data} has at least 5 rows - -07. Filter propertyCode - ${data}= Run method getDataProducts with filter propertyCode="oxygen" - Elements in ${data}[0] have the expected fields for getDataProducts - List ${data} has at least 10 rows - -09. No data products found - Run Keyword And Expect Error *404* Run method getDataProducts with filters ${F_NO_RESULTS} diff --git a/tests/robot/suites/07__data_product_delivery.robot b/tests/robot/suites/07__data_product_delivery.robot deleted file mode 100644 index 54f12d5..0000000 --- a/tests/robot/suites/07__data_product_delivery.robot +++ /dev/null @@ -1,153 +0,0 @@ -# Data product delivery tests. -# Note that downloaded files for each test are output into a different folder; This avoids race conditions when running in parallel -*** Settings *** -Documentation 07. Data Product Delivery Test Suite -Library OperatingSystem -Library Collections -Resource ../resources/general.robot -Library ../libraries/delivery.py - - -*** Variables *** - -&{F_DUMMY1}= dataProductCode=TSSD extension=csv locationCode=BACAX deviceCategoryCode=ADCP2MHZ -... dateFrom=2016-07-27T00:00:00.000Z dateTo=2016-07-27T00:00:30.000Z -... dpo_dataGaps=0 dpo_qualityControl=1 dpo_resample=none -&{F_DUMMY2}= dataProductCode=TSSP extension=png locationCode=CRIP.C1 deviceCategoryCode=CTD -... dateFrom=2019-08-29T00:00:00.000Z dateTo=2019-08-30T00:00:00.000Z -... dpo_qualityControl=1 dpo_resample=none -&{F_FAKE}= dataProductCode=FAKECODE extension=XYZ locationCode=AREA51 deviceCategoryCode=AK47 -... dateFrom=2019-03-20T00:00:00.000Z dateTo=2019-03-20T00:30:00.000Z -... dpo_qualityControl=1 dpo_resample=none - - -*** Test Cases *** - -01. Order product links only - Prepare output directory output/07/01 - ${data}= Order product ${F_DUMMY1} with resultsOnly ${True}, metadata ${False}, save to "output/07/01" - ${rows}= Set Variable ${data['downloadResults']} - List ${rows} has exactly 1 rows - Elements in ${rows[0]} have the expected fields for orderDataProduct - Element ${rows[0]} with index 1 was completed and not downloaded - Downloaded 0 files to output/07/01 - -02. Order links with metadata - Prepare output directory output/07/02 - ${data}= Order product ${F_DUMMY1} with resultsOnly ${True}, metadata ${True}, save to "output/07/02" - ${rows}= Set Variable ${data['downloadResults']} - List ${rows} has exactly 2 rows - Elements in ${rows}[0] have the expected fields for orderDataProduct - Element ${rows}[0] with index 1 was completed and not downloaded - Element ${rows}[1] with index meta was completed and not downloaded - Downloaded 0 files to output/07/02 - -03. Order and download - Prepare output directory output/07/03 - ${data}= Order product ${F_DUMMY1} with resultsOnly ${False}, metadata ${False}, save to "output/07/03" - ${rows}= Set Variable ${data['downloadResults']} - List ${rows} has exactly 1 rows - Elements in ${rows}[0] have the expected fields for orderDataProduct - Element ${rows}[0] with index 1 was completed and downloaded - Downloaded 1 files to output/07/03 - -04. Order and download multiple - Prepare output directory output/07/04 - ${data}= Order product ${F_DUMMY2} with resultsOnly ${False}, metadata ${False}, save to "output/07/04" - ${rows}= Set Variable ${data['downloadResults']} - List ${rows} has exactly 2 rows - Elements in ${rows}[0] have the expected fields for orderDataProduct - Element ${rows}[0] with index 1 was completed and downloaded - Element ${rows}[1] with index 2 was completed and downloaded - Downloaded 2 files to output/07/04 - -05. Order and download with metadata - Prepare output directory output/07/05 - ${data}= Order product ${F_DUMMY1} with resultsOnly ${False}, metadata ${True}, save to "output/07/05" - ${rows}= Set Variable ${data['downloadResults']} - List ${rows} has exactly 2 rows - Elements in ${rows}[0] have the expected fields for orderDataProduct - Element ${rows}[0] with index 1 was completed and downloaded - Element ${rows}[1] with index meta was completed and downloaded - Downloaded 2 files to output/07/05 - -06. Order and download multiple with metadata - Prepare output directory output/07/06 - ${data}= Order product ${F_DUMMY2} with resultsOnly ${False}, metadata ${True}, save to "output/07/06" - ${rows}= Set Variable ${data['downloadResults']} - List ${rows} has exactly 3 rows - Elements in ${rows}[0] have the expected fields for orderDataProduct - Element ${rows}[0] with index 1 was completed and downloaded - Element ${rows}[1] with index 2 was completed and downloaded - Element ${rows}[2] with index meta was completed and downloaded - Downloaded 3 files to output/07/06 - -07. Wrong order request argument - Run Keyword And Expect Error * Order Product filters=&{F_FAKE} retries=${0} resultsOnly=${True} metadata=${True} outPath=output/07/07 - -08. Manual request, run and download - Prepare output directory output/07/08 - ${reqId}= Manual request with filters ${F_DUMMY1} - ${runId}= Manual run with request id=${reqId} - ${rows}= Manual download with runId=${runId}, resultOnly=${False}, save to "output/07/08" - List ${rows} has exactly 2 rows - Element ${rows}[0] with index 1 was completed and downloaded - Element ${rows}[1] with index meta was completed and downloaded - Downloaded 2 files to output/07/08 - -09. Manual request, run and download results only - [Tags] run - Prepare output directory output/07/09 - ${reqId}= Manual request with filters ${F_DUMMY1} - ${runId}= Manual run with request id=${reqId} - ${rows}= Manual download with runId=${runId}, resultOnly=${True}, save to "output/07/09" - List ${rows} has exactly 2 rows - Element ${rows}[0] with index 1 was completed and not downloaded - Element ${rows}[1] with index meta was completed and not downloaded - Downloaded 0 files to output/07/09 - - -*** Keywords *** - -# Wraps Order Product with embedded arguments -Order product ${fil} with resultsOnly ${resultsOnly}, metadata ${metadata}, save to "${outPath}" - ${response}= Order Product ${fil} ${0} ${resultsOnly} ${metadata} ${outPath} - [Return] ${response} - -Order Product - [Arguments] ${filters}={None} ${retries}=${0} ${resultsOnly}=${true} ${metadata}=${False} ${outPath}=output - Prepare output directory ${outPath} - ${onc}= Make ONC with path ${outPath} - ${response}= Call Method ${onc} orderDataProduct filters=&{filters} maxRetries=${0} downloadResultsOnly=${resultsOnly} includeMetadataFile=${metadata} - [Return] ${response} - -Manual request with filters ${filters} - ${dataRequest}= Manual Request Product ${filters} - Dictionary Should Contain Key ${dataRequest} dpRequestId - ${reqId}= Get From Dictionary ${dataRequest} dpRequestId - [Return] ${reqId} - -Manual run with request id=${reqId} - ${runRequest}= Manual Run Product ${reqId} - ${runIds}= Get From Dictionary ${runRequest} runIds - [Return] ${runIds}[0] - -Manual download with runId=${runId}, resultOnly=${resultsOnly}, save to "${outPath}" - Prepare output directory ${outPath} - ${rows}= manualDownloadProduct ${runId} ${outPath} ${resultsOnly} - Should Not Be Empty ${rows} - [Return] ${rows} - -Element ${data} with index ${index} was completed and downloaded - Should Be Equal ${data}[status] complete - Should Be Equal ${data}[downloaded] ${True} - Should Be Equal ${data}[index] ${index} - Should Not Be Empty ${data}[url] - Should Not Be Empty ${data}[file] - -Element ${data} with index ${index} was completed and not downloaded - Should Be Equal ${data}[status] complete - Should Be Equal ${data}[downloaded] ${False} - Should Be Equal ${data}[index] ${index} - Should Not Be Empty ${data}[url] - Should Be Empty ${data}[file] diff --git a/tests/robot/suites/08__realtime.robot b/tests/robot/suites/08__realtime.robot deleted file mode 100644 index 3ccd52c..0000000 --- a/tests/robot/suites/08__realtime.robot +++ /dev/null @@ -1,79 +0,0 @@ -*** Settings *** -Library OperatingSystem -Library String -Documentation 08. Real-Time Test Suite -Resource ../resources/general.robot - - -*** Variables *** - -# 1 page of temperature, by location -&{F_SCALAR1} locationCode=CRIP.C1 deviceCategoryCode=CTD propertyCode=density -... dateFrom=2018-03-24T00:00:00.000Z dateTo=2018-03-24T00:00:15.000Z -# 3 pages of temperature, by location -&{F_SCALAR2} locationCode=CRIP.C1 deviceCategoryCode=CTD propertyCode=density -... dateFrom=2018-03-24T00:00:00.000Z dateTo=2018-03-24T00:00:15.000Z rowLimit=5 -# 3 pages of temperature -&{F_SCALAR3} deviceCode=BARIX001 dateFrom=2017-06-08T00:00:00.000Z dateTo=PT7M rowLimit=5 - -&{F_RAW1} locationCode=CRIP.C1 deviceCategoryCode=CTD -... dateFrom=2018-03-24T00:00:00.000Z dateTo=2018-03-24T00:00:10.000Z -&{F_RAW3} locationCode=CRIP.C1 deviceCategoryCode=CTD -... dateFrom=2018-03-24T00:00:00.000Z dateTo=2018-03-24T00:01:30.000Z rowLimit=5 -&{F_RAWDEV1} deviceCode=BARIX001 dateFrom=2017-06-08T00:00:00.000Z dateTo=PT5S -&{F_WRONG_FILTERS} locationCode=ONION deviceCategoryCode=POTATO propertyCode=BANANA -... dateFrom=2018-03-24T00:00:00.000Z dateTo=2018-03-24T00:00:10.000Z -&{F_NODATA} locationCode=CRIP.C1 deviceCategoryCode=CTD -... dateFrom=2015-03-24T00:00:00.000Z dateTo=2015-03-24T00:00:10.000Z - - -*** Test Cases *** - -1. Get scalar data by location with 1 page - ${response}= Run method getDirectByLocation with filters ${F_SCALAR1} - ${sensorData}= Get From Dictionary ${response} sensorData - First row in ${sensorData} has key "data" - First row in ${sensorData} has key "sensorCode" with value "density" - No next page in ${response} - -2. Get scalar data by location with 3 pages - ${response}= Run method getDirectByLocation with ${F_SCALAR2} and parameter ${True} - ${sensorData}= Get From Dictionary ${response} sensorData - First row in ${sensorData} has key "data" - First row in ${sensorData} has key "sensorCode" with value "density" - List ${sensorData}[0][data][values] has exactly 15 rows - No next page in ${response} - #Save Json To File ${data} out_realtime_2.json - -5. Get raw data by location with 1 page - ${response}= Run method getDirectRawByLocation with filters ${F_RAW1} - List ${response}[data][readings] has exactly 10 rows - No next page in ${response} - -6. Get raw data by location with 3 pages - ${response}= Run method getDirectRawByLocation with ${F_RAW3} and parameter ${True} - List ${response}[data][readings] has exactly 90 rows - No next page in ${response} - #Save Json To File ${data} out_realtime_6.json - -7. Raw data by device with 1 page - ${response}= Run method getDirectRawByDevice with filters ${F_RAWDEV1} - List ${response}[data][readings] has exactly 47 rows - No next page in ${response} - -10. Get scalar data by device with 6 pages - [Tags] run - ${response}= Run method getDirectByDevice with ${F_SCALAR3} and parameter ${True} - ${sensorData}= Get From Dictionary ${response} sensorData - First row in ${sensorData} has key "data" - First row in ${sensorData} has key "sensorCode" with value "analog_input501" - List ${sensorData}[0][data][values] has exactly 14 rows - No next page in ${response} - Save Json To File ${response} output/08/10/out_realtime_10.json - - -*** Keywords *** - -No next page in ${response} - Should Be Equal ${response}[next] ${None} - diff --git a/tests/robot/suites/09__archivefiles.robot b/tests/robot/suites/09__archivefiles.robot deleted file mode 100644 index 8f5d00c..0000000 --- a/tests/robot/suites/09__archivefiles.robot +++ /dev/null @@ -1,100 +0,0 @@ -# Archivefiles test suite -# Downloaded files each go to their own test folder to avoid race conditions -# Requires a "token" provided as an execution argument (ie --variable token:ABC123) - -*** Settings *** -Documentation 09. Archive Files Test Suite -Resource ../resources/general.robot - - -*** Variables *** - -${onc0} Make ONC with path output/09 -&{F_LOCATION1} locationCode=RISS deviceCategoryCode=VIDEOCAM dateFrom=2016-12-01T00:00:00.000Z dateTo=2016-12-01T01:00:00.000Z -&{F_LOCATION3} locationCode=RISS deviceCategoryCode=VIDEOCAM dateFrom=2016-12-01T00:00:00.000Z dateTo=2016-12-01T01:00:00.000Z rowLimit=5 -&{F_LOCATIONFULL} locationCode=RISS deviceCategoryCode=VIDEOCAM dateFrom=2016-12-01T00:00:00.000Z dateTo=2016-12-01T01:00:00.000Z extension=mp4 -&{F_LOC_RETURN1} locationCode=RISS deviceCategoryCode=VIDEOCAM dateFrom=2016-12-01T00:00:00.000Z dateTo=2016-12-01T01:00:00.000Z rowLimit=5 returnOptions=archiveLocation -&{F_DIRECT_WRONG} locationCode=RISS dateFrom=2016-12-01T00:00:00.000Z dateTo=2016-12-01T01:00:00.000Z -&{F_LOC_RETURN2} locationCode=RISS deviceCategoryCode=VIDEOCAM dateFrom=2016-12-01T00:00:00.000Z dateTo=2016-12-03T00:00:00.000Z rowLimit=50 returnOptions=all extension=mp4 -&{F_LOC_WRONG} dateFrom=2010-01-01T00:00:00.000Z dateTo=2010-01-01T00:02:00.000Z -&{F_DEVICE1EXT} deviceCode=NAXYS_HYD_007 dateFrom=2010-01-01T00:00:00.000Z dateTo=2010-01-01T00:02:00.000Z extension=mp3 -&{F_GETDIRECT_DEV} dateFrom=2010-01-01T00:00:00.000Z dateTo=2010-01-01T00:00:30.000Z deviceCode=NAXYS_HYD_007 returnOptions=all -&{F_GETDIRECT_LOC} dateFrom=2016-12-01T00:00:00.000Z dateTo=2016-12-01T01:00:00.000Z locationCode=RISS deviceCategoryCode=VIDEOCAM extension=mp4 - - -*** Test Cases *** - -1. Get list by location, 1 page - ${result}= Run method getListByLocation with filters &{F_LOCATION1} - List ${result}[files] has at least 13 rows - -2. Get list by location, 3 pages - ${result}= Run method getListByLocation with &{F_LOCATION1} and parameter ${True} - List ${result}[files] has at least 13 rows - -3. Get list by location, 1 page, filter by extension - ${result}= Run method getListByLocation with filters &{F_LOCATIONFULL} - List ${result}[files] has exactly 1 rows - -5. Get list by device, 1 page, filter by extension - ${result}= Run method getListByDevice with filters &{F_DEVICE1EXT} - List ${result}[files] has exactly 4 rows - -6. Get a file - Prepare output directory output/09/06 - Get file with name "NAXYS_HYD_007_20091231T235919.476Z-spect-small.png" and save to "output/09/06" - File was downloaded output/09/06/NAXYS_HYD_007_20091231T235919.476Z-spect-small.png - -7. Get direct files from device, include returnOptions - Prepare output directory output/09/07 - ${result}= GetDirectFiles with filters &{F_GETDIRECT_DEV} and save to "output/09/07" - Downloaded 12 files to output/09/07 - List ${result}[downloadResults] has exactly 12 rows - -8. Get direct files from location, try to overwrite - Prepare output directory output/09/08 - ${result}= GetDirectFiles with filters &{F_GETDIRECT_LOC} and save to "output/09/08" - List ${result}[downloadResults] has exactly 1 rows - First row in ${result}[downloadResults] has key "status" with value "completed" - Downloaded 1 files to output/09/08 - ${result}= GetDirectFiles with filters &{F_GETDIRECT_LOC} and save to "output/09/08" - List ${result}[downloadResults] has exactly 1 rows - First row in ${result}[downloadResults] has key "status" with value "skipped" - Downloaded 1 files to output/09/08 - -10. Wrong getDirectFile parameters - [Tags] run - ${onc}= Make ONC with path output/09/10 - Run Keyword And Expect Error *combination* Call Method ${onc} getDirectFiles filters=${F_DIRECT_WRONG} - -12. Get list by location, 3 pages, return archiveLocations - ${result}= Run method getListByLocation with &{F_LOC_RETURN1} and parameter ${True} - List ${result}[files] has at least 13 rows - First row in ${result}[files] has key "archiveLocation" - -13. Get list by device, 3 pages, filter extension, return all metadata per sample - ${result}= Run method getListByLocation with &{F_LOC_RETURN2} and parameter ${True} - List ${result}[files] has exactly 2 rows - First row in ${result}[files] has key "uncompressedFileSize" - -14. Save a file to current directory (empty outpath) - Get file with name "NAXYS_HYD_007_20091231T235919.476Z-spect-small.png" and save to "" - File was downloaded NAXYS_HYD_007_20091231T235919.476Z-spect-small.png - # clean up - Remove File NAXYS_HYD_007_20091231T235919.476Z-spect-small.png - -*** Keywords *** - -File was downloaded - [Arguments] ${file} - File Should Exist ${EXECDIR}${/}${file} - -Get file with name "${file}" and save to "${path}" - ${onc}= Make ONC with path ${path} - Call Method ${onc} getFile filename=${file} - -GetDirectFiles with filters ${filters} and save to "${path}" - Log ${filters} - ${onc}= Make ONC with path ${path} - ${result}= Call Method ${onc} getDirectFiles filters=${filters} - [return] ${result} \ No newline at end of file diff --git a/tests/robot/testall b/tests/robot/testall deleted file mode 100644 index 7dc46aa..0000000 --- a/tests/robot/testall +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -echo "This script runs the robot framework tests" - -# Prints usage message -usage() -{ - echo "Usage: testall [--token | -t YOUR_TOKEN] [--parallel | -p]" -} - -# Detect parameters -parallel= -token= -while [ "$1" != "" ]; do - case $1 in - -t | --token ) shift - token=$1 - ;; - -p | --parallel ) parallel=1 - ;; - * ) usage - exit 1 - esac - shift -done - - -##### Main - -# uninstall onc library in case an older version exists -pip uninstall -y onc - -if [ "$token" == "" ]; then - # Kill if no token - usage - exit 1 -fi - -if [ "$parallel" == "1" ]; then - # Execute tests in parallel - pabot --testlevelsplit --outputdir report --loglevel DEBUG --variable token:$token suites -else - # Normal robot execution - robot --outputdir report --loglevel DEBUG --variable token:$token suites -fi diff --git a/tests/robot/testcoverage b/tests/robot/testcoverage deleted file mode 100644 index 683b015..0000000 --- a/tests/robot/testcoverage +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -echo "This script obtains the code coverage for the robot framework tests" - -# Prints usage message -usage() -{ - echo "Usage: testcoverage [--token | -t YOUR_TOKEN] [--suite | -s SUITE_NUMBER(0-99)]" -} - -# Detect parameters -parallel= -token= -suite= -while [ "$1" != "" ]; do - case $1 in - -t | --token ) shift - token=$1 - ;; - -s | --suite ) shift - suite=$1 - ;; - * ) usage - exit 1 - esac - shift -done - -# Print test suites if we didn't get a suite number -if [ "$suite" == "" ]; then - echo "Test suites available:" -fi - -# Get a list of test suites -i=0 -for file in $PWD/suites/* -do - filename=$(echo $file | cut -d'/' -f 8) - names[$i]="$filename" - ((i++)) -done - -# run tests -if [ "$suite" == "" ]; then - echo "Running all tests" - coverage run -m robot --outputdir report --loglevel DEBUG --variable token:$token suites -else - echo "Running suite: ${names[$suite]}" - coverage run -m robot --outputdir report --loglevel DEBUG --variable token:$token suites/${names[$suite]} -fi - -# print console report -coverage report --include *onc/* - -# generate HTML report -coverage html --include *onc/* -echo HTML report generated at: $PWD/htmlcov/index.html diff --git a/tests/robot/testsuite b/tests/robot/testsuite deleted file mode 100644 index ec26278..0000000 --- a/tests/robot/testsuite +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash -# Promts the user to specify a suite number and runs it -# Number can also be included as an argument (i.e. "testsite 5") - -# Prints usage message -usage() -{ - echo "Usage: testsuite [--token | -t YOUR_TOKEN] [--suite | -s SUITE_NUMBER(0-99)] [--parallel | -p]" -} - -# Detect parameters -parallel= -token= -suite= -while [ "$1" != "" ]; do - case $1 in - -t | --token ) shift - token=$1 - ;; - -s | --suite ) shift - suite=$1 - ;; - -p | --parallel ) parallel=1 - ;; - * ) usage - exit 1 - esac - shift -done - -# Print test suites if we didn't get a suite number -if [ "$suite" == "" ]; then - echo "Test suites available:" -fi - -# Get a list of test suites -i=0 -for file in $PWD/suites/* -do - filename=$(echo $file | cut -d'/' -f 8) - names[$i]="$filename" - # Print the list of suites if we didn't get a suite number - if [ "$suite" == "" ]; then - echo ${names[i]} - fi - ((i++)) -done - -# Kill if no token or suite number -if [ "$token" == "" ] || [ "$suite" == "" ]; then - usage - exit 1 -fi - -##### Main - -echo Executing: ${names[suite]} -if [ "$parallel" == "1" ]; then - # Execute tests in parallel - pabot --testlevelsplit --outputdir report --loglevel DEBUG --variable token:$token suites/${names[suite]} -else - # Normal robot execution - robot --outputdir report --loglevel DEBUG --variable token:$token suites/${names[suite]} -fi \ No newline at end of file diff --git a/tests/scalar_data/test_scalardata_device.py b/tests/scalar_data/test_scalardata_device.py new file mode 100644 index 0000000..929ab81 --- /dev/null +++ b/tests/scalar_data/test_scalardata_device.py @@ -0,0 +1,68 @@ +import pytest +import requests + + +@pytest.fixture +def params(): + return { + "deviceCode": "BPR-Folger-59", + "dateFrom": "2019-11-23T00:00:00.000Z", + "dateTo": "2019-11-23T00:01:00.000Z", + "rowLimit": 80000, + } + + +@pytest.fixture +def params_multiple_pages(params): + # rowLimit should be less than the total number of rows. + return params | {"rowLimit": 25} + + +def test_invalid_param_value(requester, params): + params_invalid_param_value = params | {"deviceCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getDirectByDevice(params_invalid_param_value) + + +def test_invalid_param_name(requester, params): + params_invalid_param_name = params | {"deviceCodes": "BPR-Folger-59"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getDirectByDevice(params_invalid_param_name) + + +def test_no_data(requester, params): + params_no_data = params | {"dateFrom": "2000-01-01", "dateTo": "2000-01-02"} + data = requester.getDirectByDevice(params_no_data) + + assert data["sensorData"] is None + + +def test_valid_params_one_page(requester, params, params_multiple_pages): + data = requester.getDirectByDevice(params) + data_all_pages = requester.getDirectByDevice(params_multiple_pages, allPages=True) + + assert ( + _get_row_num(data) > params_multiple_pages["rowLimit"] + ), "Test should return at least `rowLimit` rows for each sensor." + + assert data["next"] is None, "Test should return only one page." + + assert ( + data_all_pages["sensorData"][0]["data"] == data["sensorData"][0]["data"] + ), "Test should concatenate rows for all pages." + + assert data_all_pages["next"] is None, "Test should return only one page." + + +def test_valid_params_multiple_pages(requester, params_multiple_pages): + data = requester.getDirectByDevice(params_multiple_pages) + + assert ( + _get_row_num(data) == params_multiple_pages["rowLimit"] + ), "Test should only return `rowLimit` rows for each sensor." + + assert data["next"] is not None, "Test should return multiple pages." + + +def _get_row_num(data): + return len(data["sensorData"][0]["data"]["values"]) diff --git a/tests/scalar_data/test_scalardata_location.py b/tests/scalar_data/test_scalardata_location.py new file mode 100644 index 0000000..0d0327e --- /dev/null +++ b/tests/scalar_data/test_scalardata_location.py @@ -0,0 +1,69 @@ +import pytest +import requests + + +@pytest.fixture +def params(): + return { + "locationCode": "NCBC", + "deviceCategoryCode": "BPR", + "propertyCode": "seawatertemperature,totalpressure", + "dateFrom": "2019-11-23T00:00:00.000Z", + "dateTo": "2019-11-23T00:01:00.000Z", + "rowLimit": 80000, + } + + +@pytest.fixture +def params_multiple_pages(params): + # rowLimit should be less than the total number of rows. + return params | {"rowLimit": 25} + + +def test_invalid_param_value(requester, params): + params_invalid_param_value = params | {"locationCode": "XYZ123"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getDirectByLocation(params_invalid_param_value) + + +def test_invalid_param_name(requester, params): + params_invalid_param_name = params | {"locationCodes": "NCBC"} + with pytest.raises(requests.HTTPError, match=r"API Error 129"): + requester.getDirectByLocation(params_invalid_param_name) + + +def test_no_data(requester, params): + params_no_data = params | {"dateFrom": "2000-01-01", "dateTo": "2000-01-02"} + with pytest.raises(requests.HTTPError, match=r"API Error 127"): + requester.getDirectByLocation(params_no_data) + + +def test_valid_params_one_page(requester, params, params_multiple_pages): + data = requester.getDirectByLocation(params) + data_all_pages = requester.getDirectByLocation(params_multiple_pages, allPages=True) + + assert ( + _get_row_num(data) > params_multiple_pages["rowLimit"] + ), "Test should return at least `rowLimit` rows for each sensor." + + assert data["next"] is None, "Test should return only one page." + + assert ( + data_all_pages["sensorData"][0]["data"] == data["sensorData"][0]["data"] + ), "Test should concatenate rows for all pages." + + assert data_all_pages["next"] is None, "Test should return only one page." + + +def test_valid_params_multiple_pages(requester, params_multiple_pages): + data = requester.getDirectByLocation(params_multiple_pages) + + assert ( + _get_row_num(data) == params_multiple_pages["rowLimit"] + ), "Test should only return `rowLimit` rows for each sensor." + + assert data["next"] is not None, "Test should return multiple pages." + + +def _get_row_num(data): + return len(data["sensorData"][0]["data"]["values"]) diff --git a/tests/test_archive_files.py b/tests/test_archive_files.py deleted file mode 100644 index a29cad5..0000000 --- a/tests/test_archive_files.py +++ /dev/null @@ -1,31 +0,0 @@ -import pytest -import requests - - -@pytest.fixture -def f_location1(): - return { - "locationCode": "RISS", - "deviceCategoryCode": "VIDEOCAM", - "dateFrom": "2016-12-01T00:00:00.000Z", - "dateTo": "2016-12-01T01:00:00.000Z", - } - - -def test_missing_deviceCategoryCode(requester): - with pytest.raises(requests.HTTPError, match=r"Error 128"): - loc_wrong = { - "dateFrom": "2010-01-01T00:00:00.000Z", - "dateTo": "2010-01-01T00:02:00.000Z", - } - requester.getListByLocation(filters=loc_wrong) - - -def test_wrong_getFile_filename(requester): - with pytest.raises(requests.HTTPError, match=r"Error 96"): - requester.getFile(filename="FAKEFILE.XYZ") - - -def test_wrong_getList_invalid_filters(requester, f_location1): - with pytest.raises(requests.HTTPError, match=r"Error 129"): - requester.getListByDevice(filters=f_location1) diff --git a/tests/test_data_product_delivery.py b/tests/test_data_product_delivery.py deleted file mode 100644 index 4867b8f..0000000 --- a/tests/test_data_product_delivery.py +++ /dev/null @@ -1,12 +0,0 @@ -import pytest -import requests - - -def test_download_wrong_runID(requester): - with pytest.raises(requests.HTTPError, match=r"Error 127"): - requester.downloadDataProduct(1234567890) - - -def test_run_wrong_runID(requester): - with pytest.raises(requests.HTTPError, match=r"Error 127"): - requester.runDataProduct(1234567890) diff --git a/tests/test_data_product_discovery.py b/tests/test_data_product_discovery.py deleted file mode 100644 index 6d17136..0000000 --- a/tests/test_data_product_discovery.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest -import requests - - -def test_wrong_dataProductCode(requester): - with pytest.raises(requests.HTTPError, match=r"Error 127"): - requester.getDataProducts(filters={"dataProductCode": "XYZ123"}) diff --git a/tests/test_deployments.py b/tests/test_deployments.py deleted file mode 100644 index c1b8b23..0000000 --- a/tests/test_deployments.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest -import requests - - -def test_wrong_locationCode(requester): - with pytest.raises(requests.HTTPError, match=r"Error 127"): - requester.getDataProducts(filters={"locationCode": "XYZ123"}) diff --git a/tests/test_device_categories.py b/tests/test_device_categories.py deleted file mode 100644 index 8110e4c..0000000 --- a/tests/test_device_categories.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest -import requests - - -def test_wrong_deviceCategoryCode(requester): - with pytest.raises(requests.HTTPError, match=r"Error 127"): - requester.getDataProducts(filters={"deviceCategoryCode": "XYZ123"}) diff --git a/tests/test_devices.py b/tests/test_devices.py deleted file mode 100644 index afdf930..0000000 --- a/tests/test_devices.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest -import requests - - -def test_wrong_deviceCode(requester): - with pytest.raises(requests.HTTPError, match=r"Error 127"): - requester.getDataProducts(filters={"deviceCode": "XYZ123"}) diff --git a/tests/test_locations.py b/tests/test_locations.py deleted file mode 100644 index a6e55a2..0000000 --- a/tests/test_locations.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest -import requests - - -def test_wrong_locationCode(requester): - with pytest.raises(requests.HTTPError, match=r"Error 127"): - requester.getLocations(filters={"locationCode": "XYZ123"}) diff --git a/tests/test_properties.py b/tests/test_properties.py deleted file mode 100644 index a84b3f5..0000000 --- a/tests/test_properties.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest -import requests - - -def test_wrong_propertyCode(requester): - with pytest.raises(requests.HTTPError, match=r"Error 127"): - requester.getLocations(filters={"propertyCode": "XYZ123"}) diff --git a/tests/test_realtime.py b/tests/test_realtime.py deleted file mode 100644 index 3c161a3..0000000 --- a/tests/test_realtime.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytest -import requests - - -@pytest.fixture -def no_data_filters(): - return { - "locationCode": "CRIP.C1", - "deviceCategoryCode": "CTD", - "dateFrom": "2015-03-24T00:00:00.000Z", - "dateTo": "2015-03-24T00:00:10.000Z", - } - - -@pytest.fixture -def bad_data_filters(no_data_filters): - return {**no_data_filters, "propertyCode": "BANANA"} - - -def test_no_data_filters(requester, no_data_filters): - with pytest.raises(requests.HTTPError, match=r"Error 127"): - requester.getDirectByLocation(filters=no_data_filters) - - -def test_bad_filters(requester, bad_data_filters): - with pytest.raises(requests.HTTPError, match=r"Error 127"): - requester.getDirectByLocation(filters=bad_data_filters) - - -def test_raw_no_data_filters(requester, no_data_filters): - with pytest.raises(requests.HTTPError, match=r"Error 127"): - requester.getDirectRawByLocation(filters=no_data_filters) - - -def test_raw_bad_filters(requester, bad_data_filters): - with pytest.raises(requests.HTTPError, match=r"Error 129"): - requester.getDirectRawByLocation(filters=bad_data_filters) diff --git a/tox.ini b/tox.ini index 3ab8090..35bb1e2 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] min_version = 4.0 env_list = - py38 + py39 format-check lint isolated_build = True @@ -9,13 +9,12 @@ isolated_build = True [testenv] description = run unit tests deps = - robotframework python-dotenv pytest + pytest-cov passenv = TOKEN commands = - robot tests/robot/suites - pytest + pytest --cov=onc [testenv:format] description = run black and isort @@ -44,7 +43,6 @@ commands = ruff check {posargs:src tests} [gh] python = - 3.8 = py38 3.9 = py39 3.10 = py310, format-check, lint 3.11 = py311