Commit 15bceff00febc860db45c15bb819c60ef38806a2
Exists in
rhitier-dev
and in
1 other branch
Merge branch 'UnitTesting' into dev
Showing
5 changed files
with
201 additions
and
107 deletions
Show diff stats
DEV.md
... | ... | @@ -5,4 +5,15 @@ |
5 | 5 | * go to config.yml |
6 | 6 | 1. add new entry to 'inputs' section |
7 | 7 | 2. inside each target, add entry in the 'models' sub-section |
8 | -* possible to set default input in the defaults.input_slug parameter | |
9 | 8 | \ No newline at end of file |
9 | +* possible to set default input in the defaults.input_slug parameter | |
10 | + | |
11 | +## Testing | |
12 | + | |
13 | + # basic | |
14 | + PYTHONPATH=. pytest | |
15 | + | |
16 | + # debug messages enabled | |
17 | + DEBUG=true PYTHONPATH=. pytest | |
18 | + | |
19 | + # output to stderr activated | |
20 | + DEBUG=true PYTHONPATH=. pytest -rP | ... | ... |
... | ... | @@ -0,0 +1,83 @@ |
1 | +import gzip | |
2 | +import os.path | |
3 | +import sys | |
4 | +import unittest | |
5 | +from datetime import datetime as ddatetime, datetime | |
6 | +from pprint import pprint | |
7 | + | |
8 | +import numpy.ma.core | |
9 | +from netCDF4 import Dataset | |
10 | + | |
11 | +from web.run import retrieve_amda_netcdf, get_data_for_target, _sta_sto, _read_var, default_nc_keys | |
12 | + | |
13 | +FILE_DATE_FMT = "%Y-%m-%d %H:%M:%S" | |
14 | + | |
15 | + | |
16 | +class BaseTestCase(unittest.TestCase): | |
17 | + def setUp(self): | |
18 | + # initialise app | |
19 | + # self.app = create_app(TestConfig) | |
20 | + | |
21 | + # update flask context | |
22 | + # self.app_context = self.app.app_context() | |
23 | + # self.app_context.push() | |
24 | + pass | |
25 | + | |
26 | + def tearDown(self): | |
27 | + # if os.path.isfile(self.db_path): | |
28 | + # os.remove(self.db_path) | |
29 | + # self.app_context.pop() | |
30 | + pass | |
31 | + | |
32 | + def test_always_true(self): | |
33 | + self.assertTrue(True) | |
34 | + | |
35 | + | |
36 | +class AmdaTestCase(BaseTestCase): | |
37 | + | |
38 | + def test_amda_retrieve(self): | |
39 | + started_at = ddatetime.strptime("2021-12-17 00:00:00", FILE_DATE_FMT) | |
40 | + stopped_at = ddatetime.strptime("2021-12-18 00:00:00", FILE_DATE_FMT) | |
41 | + amda_list = retrieve_amda_netcdf("earth", "omni_hour_all", started_at, stopped_at) | |
42 | + self.assertEqual(1, len(amda_list)) | |
43 | + self.assertIn('amda-irap-omp-eu-ddservice-base-data-omni-hour-omni202107010-nc', amda_list[0]) | |
44 | + | |
45 | + def test_get_data_for_target(self): | |
46 | + target_config = {'type': 'planet', 'slug': 'earth', 'name': 'Earth', 'title': 'Earth', 'orbit': {'models': []}, | |
47 | + 'models': { | |
48 | + 'om': [{'slug': 'omni_hour_all', 'parameters': {'pdyn': 'RamP'}}, | |
49 | + {'slug': 'ace_swepam_real_1h', | |
50 | + 'parameters': {'dens': 'Dens', 'vtot': 'Vel', 'temp': 'Temp'}}], | |
51 | + 'sa': [{'slug': 'omni_hour_all', 'parameters': {'pdyn': 'RamP'}}, | |
52 | + {'slug': 'ace_swepam_real_1h', | |
53 | + 'parameters': {'dens': 'Dens', 'vtot': 'Vel', 'temp': 'Temp'}}], | |
54 | + 'sb': [{'slug': 'omni_hour_all', 'parameters': {'pdyn': 'RamP'}}, | |
55 | + {'slug': 'ace_swepam_real_1h', | |
56 | + 'parameters': {'dens': 'Dens', 'vtot': 'Vel', 'temp': 'Temp'}}]}, | |
57 | + 'locked': False, 'default': True, 'catalog_layers': {'cmecatalogs': []}} | |
58 | + | |
59 | + started_at = ddatetime.strptime("2021-12-17 00:00:00", FILE_DATE_FMT) | |
60 | + stopped_at = ddatetime.strptime("2021-12-18 00:00:00", FILE_DATE_FMT) | |
61 | + model = {'parameters': {'dens': 'Dens', 'temp': 'Temp', 'vtot': 'Vel'}, 'slug': 'ace_swepam_real_1h'} | |
62 | + s0, s1 = _sta_sto(model, started_at, stopped_at) | |
63 | + all_data = get_data_for_target(target_config, 'om', s0, s1) | |
64 | + self.assertEqual(25, len(all_data)) | |
65 | + | |
66 | + def test_sta_sto(self): | |
67 | + started_at = ddatetime.strptime("2021-12-17 00:00:00", FILE_DATE_FMT) | |
68 | + stopped_at = ddatetime.strptime("2021-12-18 00:00:00", FILE_DATE_FMT) | |
69 | + model = {'parameters': {'dens': 'Dens', 'temp': 'Temp', 'vtot': 'Vel'}, 'slug': 'ace_swepam_real_1h'} | |
70 | + | |
71 | + s0, s1 = _sta_sto(model, started_at, stopped_at) | |
72 | + | |
73 | + self.assertIsInstance(s0, datetime) | |
74 | + self.assertIsInstance(s1, datetime) | |
75 | + | |
76 | + def test_var_read_nc_float32(self): | |
77 | + SCRIPT_PATH = os.path.dirname(__file__) | |
78 | + PROJECT_DIR = os.path.abspath(os.path.join(SCRIPT_PATH, os.pardir)) | |
79 | + local_netc_file = os.path.join(PROJECT_DIR,'tests-resources', 'amda-irap-omp-eu-ddservice-base-data-omni-hour-omni202107010-nc') | |
80 | + cdf_handle = Dataset(local_netc_file, "r", format="NETCDF4") | |
81 | + nc_keys = default_nc_keys.copy() | |
82 | + data_v = _read_var(cdf_handle, nc_keys, 'vtot') | |
83 | + self.assertIsInstance(data_v[0], numpy.float32) | ... | ... |
tests/FrontEndTests.py
1 | -import urllib | |
2 | - | |
3 | -from selenium import webdriver | |
4 | -from flask_testing import LiveServerTestCase | |
5 | -from tryflask import app | |
6 | - | |
7 | -_SERVER_PORT = 8943 | |
8 | -_ROOT_URL = "http://localhost:{}".format(_SERVER_PORT) | |
9 | - | |
10 | - | |
11 | -class BaseTestCase(LiveServerTestCase): | |
12 | - def create_app(self): | |
13 | - # # remove logging lines on test output | |
14 | - import logging | |
15 | - log = logging.getLogger('werkzeug') | |
16 | - log.setLevel(logging.INFO) | |
17 | - log.disabled = True | |
18 | - # os.environ['WERKZEUG_RUN_MAIN'] = 'true' | |
19 | - | |
20 | - # pass in test configurations | |
21 | - app.config.update( | |
22 | - # Change the port that the liveserver listens on as we dont want to conflict with running:5000 | |
23 | - LIVESERVER_PORT=_SERVER_PORT | |
24 | - ) | |
25 | - | |
26 | - self.app_context = app.app_context() | |
27 | - self.app_context.push() | |
28 | - return app | |
29 | - | |
30 | - def setUp(self): | |
31 | - # os.environ["PYTHONTRACEMALLOC"] = '1' | |
32 | - | |
33 | - self.driver = self.create_chrome_driver() | |
34 | - | |
35 | - def tearDown(self): | |
36 | - self.app_context.pop() | |
37 | - self.driver.close() | |
38 | - self.driver.quit() | |
39 | - | |
40 | - def create_chrome_driver(self): | |
41 | - """ | |
42 | - Create then return the chrome driver. | |
43 | - | |
44 | - :return: the chrome driver. | |
45 | - """ | |
46 | - from selenium.webdriver.chrome.options import Options | |
47 | - options = Options() | |
48 | - options.add_argument('--headless') | |
49 | - | |
50 | - return webdriver.Chrome(options=options) | |
51 | - | |
52 | - | |
53 | -class AccessTestCase(BaseTestCase): | |
54 | - def test_ping(self): | |
55 | - self.assertEqual(_ROOT_URL, self.get_server_url()) | |
56 | - | |
57 | - def test_selenium_access(self): | |
58 | - # open browser on servers adress | |
59 | - self.driver.get(self.get_server_url()) | |
60 | - # L'adresse dans l'url doit être celle que l'on attend. | |
61 | - self.assertEqual(_ROOT_URL+'/', self.driver.current_url) | |
62 | - | |
63 | - def test_server_is_up_and_running(self): | |
64 | - response = urllib.request.urlopen(self.get_server_url()) | |
65 | - self.assertEqual(200, response.code) | |
1 | +# import urllib | |
2 | +# | |
3 | +# from selenium import webdriver | |
4 | +# from flask_testing import LiveServerTestCase | |
5 | +# | |
6 | +# _SERVER_PORT = 8943 | |
7 | +# _ROOT_URL = "http://localhost:{}".format(_SERVER_PORT) | |
8 | +# | |
9 | +# | |
10 | +# class BaseTestCase(LiveServerTestCase): | |
11 | +# def create_app(self): | |
12 | +# # # remove logging lines on test output | |
13 | +# import logging | |
14 | +# log = logging.getLogger('werkzeug') | |
15 | +# log.setLevel(logging.INFO) | |
16 | +# log.disabled = True | |
17 | +# # os.environ['WERKZEUG_RUN_MAIN'] = 'true' | |
18 | +# | |
19 | +# # pass in test configurations | |
20 | +# app.config.update( | |
21 | +# # Change the port that the liveserver listens on as we dont want to conflict with running:5000 | |
22 | +# LIVESERVER_PORT=_SERVER_PORT | |
23 | +# ) | |
24 | +# | |
25 | +# self.app_context = app.app_context() | |
26 | +# self.app_context.push() | |
27 | +# return app | |
28 | +# | |
29 | +# def setUp(self): | |
30 | +# # os.environ["PYTHONTRACEMALLOC"] = '1' | |
31 | +# | |
32 | +# self.driver = self.create_chrome_driver() | |
33 | +# | |
34 | +# def tearDown(self): | |
35 | +# self.app_context.pop() | |
36 | +# self.driver.close() | |
37 | +# self.driver.quit() | |
38 | +# | |
39 | +# def create_chrome_driver(self): | |
40 | +# """ | |
41 | +# Create then return the chrome driver. | |
42 | +# | |
43 | +# :return: the chrome driver. | |
44 | +# """ | |
45 | +# from selenium.webdriver.chrome.options import Options | |
46 | +# options = Options() | |
47 | +# options.add_argument('--headless') | |
48 | +# | |
49 | +# return webdriver.Chrome(options=options) | |
50 | +# | |
51 | +# | |
52 | +# class AccessTestCase(BaseTestCase): | |
53 | +# def test_ping(self): | |
54 | +# self.assertEqual(_ROOT_URL, self.get_server_url()) | |
55 | +# | |
56 | +# def test_selenium_access(self): | |
57 | +# # open browser on servers adress | |
58 | +# self.driver.get(self.get_server_url()) | |
59 | +# # L'adresse dans l'url doit être celle que l'on attend. | |
60 | +# self.assertEqual(_ROOT_URL+'/', self.driver.current_url) | |
61 | +# | |
62 | +# def test_server_is_up_and_running(self): | |
63 | +# response = urllib.request.urlopen(self.get_server_url()) | |
64 | +# self.assertEqual(200, response.code) | ... | ... |
... | ... | @@ -11,7 +11,8 @@ import time |
11 | 11 | import urllib.request as urllib_request |
12 | 12 | import requests |
13 | 13 | import re # regex |
14 | -import numpy | |
14 | +import numpy as np | |
15 | +import sys | |
15 | 16 | |
16 | 17 | from csv import writer as csv_writer, DictWriter as csv_dict_writer |
17 | 18 | from math import sqrt, isnan |
... | ... | @@ -79,7 +80,6 @@ logHandler.setFormatter(logging.Formatter( |
79 | 80 | )) |
80 | 81 | log.addHandler(logHandler) |
81 | 82 | |
82 | - | |
83 | 83 | # HARDCODED CONFIGURATION ##################################################### |
84 | 84 | |
85 | 85 | ASTRONOMICAL_UNIT_IN_KM = 1.496e8 |
... | ... | @@ -333,6 +333,40 @@ def datetime_from_list(time_list): |
333 | 333 | "%Y%j%H%M%S%f" |
334 | 334 | ) |
335 | 335 | |
336 | +# Override these using the model configuration in config.yml | |
337 | +default_nc_keys = { | |
338 | + 'hee': 'HEE', | |
339 | + 'vtot': 'V', | |
340 | + 'magn': 'B', | |
341 | + 'temp': 'T', | |
342 | + 'dens': 'N', | |
343 | + 'pdyn': 'P_dyn', | |
344 | + 'atse': 'Delta_angle', | |
345 | +} | |
346 | + | |
347 | +def _sta_sto(_cnf, _sta, _sto): | |
348 | + if 'started_at' in _cnf: | |
349 | + _s0 = datetime.datetime.strptime(_cnf['started_at'], FILE_DATE_FMT) | |
350 | + _s0 = max(_s0, _sta) | |
351 | + else: | |
352 | + _s0 = _sta | |
353 | + if 'stopped_at' in _cnf: | |
354 | + _s1 = datetime.datetime.strptime(_cnf['stopped_at'], FILE_DATE_FMT) | |
355 | + _s1 = min(_s1, _sto) | |
356 | + else: | |
357 | + _s1 = _sto | |
358 | + return _s0, _s1 | |
359 | + | |
360 | + | |
361 | +def _read_var(_nc, _keys, _key, mandatory=False): | |
362 | + try: | |
363 | + return _nc.variables[_keys[_key]][:] | |
364 | + except KeyError: | |
365 | + pass | |
366 | + if mandatory: | |
367 | + raise Exception("No variable '%s' found in NetCDF." % _keys[_key]) | |
368 | + return [None] * len(_nc.variables['Time']) # slow -- use numpy! | |
369 | + | |
336 | 370 | |
337 | 371 | def get_local_filename(url): |
338 | 372 | """ |
... | ... | @@ -483,10 +517,6 @@ ORDER BY time_min, granule_gid |
483 | 517 | 'external_link': row[3].text, |
484 | 518 | }) |
485 | 519 | |
486 | - # print("Auroral emission query") | |
487 | - # print(query) | |
488 | - # print("Auroral emission rows") | |
489 | - # print(rows) | |
490 | 520 | |
491 | 521 | return rows |
492 | 522 | except Exception as e: |
... | ... | @@ -654,38 +684,6 @@ def get_data_for_target(target_config, input_slug, |
654 | 684 | # abort(500, "Invalid orbit configuration for '%s' : %s" |
655 | 685 | # % (target_config['slug'], str(e))) |
656 | 686 | |
657 | - def _sta_sto(_cnf, _sta, _sto): | |
658 | - if 'started_at' in _cnf: | |
659 | - _s0 = datetime.datetime.strptime(_cnf['started_at'], FILE_DATE_FMT) | |
660 | - _s0 = max(_s0, _sta) | |
661 | - else: | |
662 | - _s0 = _sta | |
663 | - if 'stopped_at' in _cnf: | |
664 | - _s1 = datetime.datetime.strptime(_cnf['stopped_at'], FILE_DATE_FMT) | |
665 | - _s1 = min(_s1, _sto) | |
666 | - else: | |
667 | - _s1 = _sto | |
668 | - return _s0, _s1 | |
669 | - | |
670 | - def _read_var(_nc, _keys, _key, mandatory=False): | |
671 | - try: | |
672 | - return _nc.variables[_keys[_key]] | |
673 | - except KeyError: | |
674 | - pass | |
675 | - if mandatory: | |
676 | - raise Exception("No variable '%s' found in NetCDF." % _keys[_key]) | |
677 | - return [None] * len(_nc.variables['Time']) # slow -- use numpy! | |
678 | - | |
679 | - # Override these using the model configuration in config.yml | |
680 | - default_nc_keys = { | |
681 | - 'hee': 'HEE', | |
682 | - 'vtot': 'V', | |
683 | - 'magn': 'B', | |
684 | - 'temp': 'T', | |
685 | - 'dens': 'N', | |
686 | - 'pdyn': 'P_dyn', | |
687 | - 'atse': 'Delta_angle', | |
688 | - } | |
689 | 687 | |
690 | 688 | precision = "%Y-%m-%dT%H" # model and orbits times are only equal-ish |
691 | 689 | orbit_data = {} # keys are datetime as str, values arrays of XY |
... | ... | @@ -914,7 +912,6 @@ def generate_csv_file_if_needed(target_slug, input_slug, |
914 | 912 | if isfile(local_csv_file): |
915 | 913 | log.warning("Removing failed CSV '%s'..." % local_csv_file) |
916 | 914 | removefile(local_csv_file) |
917 | - # pprint(e) | |
918 | 915 | abort(500, "Failed creating CSV '%s' : %s" % (filename, e)) |
919 | 916 | |
920 | 917 | |
... | ... | @@ -1523,7 +1520,6 @@ def download_targets_cdf(targets, inp, started_at, stopped_at): |
1523 | 1520 | |
1524 | 1521 | for param in params: |
1525 | 1522 | k = "%s_%s" % (target_slug, param) |
1526 | - # print("PARAM %s" % k) | |
1527 | 1523 | values = [] |
1528 | 1524 | i = available_params.index(param) |
1529 | 1525 | has_nones = False |
... | ... | @@ -1603,7 +1599,6 @@ def download_auroral_catalog_csv(target): |
1603 | 1599 | # Filter the emissions |
1604 | 1600 | def _keep_emission(emission): |
1605 | 1601 | ok = thumbnail_url_filter.match(emission['thumbnail_url']) |
1606 | - # print("ok", ok, emission['thumbnail_url']) | |
1607 | 1602 | return bool(ok) |
1608 | 1603 | |
1609 | 1604 | emissions = [e for e in emissions if _keep_emission(e)] | ... | ... |