behave_tests: add unit tests for TestAPI client
[nfvbench.git] / test / ut_behave_tests / test_utils.py
1 #!/usr/bin/env python
2 # Copyright 2022 Orange
3 #
4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
5 #    not use this file except in compliance with the License. You may obtain
6 #    a copy of the License at
7 #
8 #         http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #    Unless required by applicable law or agreed to in writing, software
11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 #    License for the specific language governing permissions and limitations
14 #    under the License.
15 #
16
17 """
18 Utility functions for unit tests.
19 """
20
21 import json
22 import logging
23 import pathlib
24 import unittest
25 from unittest.mock import Mock
26
27
28 # -----------------------------------------------------------------------------------------
29 # Logging helpers
30 # -----------------------------------------------------------------------------------------
31
32 def setup_logging(log_filename="ut_behave_tests.log", *, log_to_console=False):
33     """Setup logging for unit tests.
34
35     Principles:
36     - re-use the global "behave_tests" logger
37     - if `log_to_console` is True, log messages up to INFO level to the console
38       (can be useful when running tests with unittest instead of pytest)
39     - if `log_filename` is provided, log messages up to DEBUG level to the log file
40     """
41     logger = logging.getLogger("behave_tests")
42     logger.setLevel(logging.DEBUG)
43     formatter = logging.Formatter("%(levelname)s:%(filename)s:%(lineno)s: %(message)s")
44
45     # Configure logging to the console
46     if log_to_console:
47         ch = logging.StreamHandler()
48         ch.setLevel(logging.INFO)
49         ch.setFormatter(formatter)
50         logger.addHandler(ch)
51
52     # Configure logging to the log file
53     if log_filename is not None:
54         fh = logging.FileHandler(filename=log_filename, mode='w')
55         fh.setLevel(logging.DEBUG)
56         fh.setFormatter(formatter)
57         logger.addHandler(fh)
58
59     return logger
60
61
62 # -----------------------------------------------------------------------------------------
63 # Test data helpers
64 # -----------------------------------------------------------------------------------------
65
66 def get_test_data_dir() -> pathlib.Path:
67     """Get absolute path of the test_data/ dir.
68
69     We need this because the unit tests can be run from different locations
70     depending on the context (tox, development, ...)
71     """
72     return pathlib.Path(__file__).parent / 'test_data'
73
74
75 def stub_requests_get(testapi_url):
76     """Mock a request to TestAPI results database.
77
78     Instead of doing a real request, build a filename from the URL suffix, find
79         the file in the `test_data` directory and return the contents of the file.
80
81     Args:
82         testapi_url: a URL starting with `http://127.0.0.1:8000/api/v1/results?`
83             and followed by the results file name without extension.
84
85     Returns:
86         A mock of a `requests.Response` object with the attributes `text` and
87             `status_code` and the method `json()`.
88     """
89     response = Mock()
90     filename_prefix = testapi_url.replace('http://127.0.0.1:8000/api/v1/results?', '')
91     if filename_prefix == testapi_url:
92         raise ValueError("For unit tests, TestAPI URL must start with "
93                          "http://127.0.0.1:8000/api/v1/results?")
94     page_filename = get_test_data_dir() / (filename_prefix + ".json")
95     try:
96         with open(page_filename, 'r', encoding='utf-8') as results:
97             response.text = results.read()
98         response.json = lambda: json.loads(response.text)
99         response.status_code = 200
100         return response
101     except FileNotFoundError as e:
102         logging.getLogger("behave_tests").exception(e)
103         raise ValueError(f"No test data available for TestAPI URL: {testapi_url}") from e
104
105
106 class TestStubRequestsGet(unittest.TestCase):
107     def test_valid_url(self):
108         response = stub_requests_get("http://127.0.0.1:8000/api/v1/results?"
109                                      "project=nfvbench&case=characterization&criteria=PASS&page=1")
110         self.assertEqual(200, response.status_code)
111         self.assertEqual("nfvbench", response.json()["results"][0]["project_name"])
112
113     def test_bad_prefix(self):
114         with self.assertRaises(ValueError):
115             stub_requests_get("http://no.way/api/v1/results?" "dummy_suffix")
116
117     def test_file_not_found(self):
118         with self.assertRaises(ValueError):
119             stub_requests_get("http://127.0.0.1:8000/api/v1/results?" "dummy_suffix")