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,4 +5,15 @@ | ||
5 | * go to config.yml | 5 | * go to config.yml |
6 | 1. add new entry to 'inputs' section | 6 | 1. add new entry to 'inputs' section |
7 | 2. inside each target, add entry in the 'models' sub-section | 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 | \ No newline at end of file | 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 @@ | @@ -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,7 +11,8 @@ import time | ||
11 | import urllib.request as urllib_request | 11 | import urllib.request as urllib_request |
12 | import requests | 12 | import requests |
13 | import re # regex | 13 | import re # regex |
14 | -import numpy | 14 | +import numpy as np |
15 | +import sys | ||
15 | 16 | ||
16 | from csv import writer as csv_writer, DictWriter as csv_dict_writer | 17 | from csv import writer as csv_writer, DictWriter as csv_dict_writer |
17 | from math import sqrt, isnan | 18 | from math import sqrt, isnan |
@@ -79,7 +80,6 @@ logHandler.setFormatter(logging.Formatter( | @@ -79,7 +80,6 @@ logHandler.setFormatter(logging.Formatter( | ||
79 | )) | 80 | )) |
80 | log.addHandler(logHandler) | 81 | log.addHandler(logHandler) |
81 | 82 | ||
82 | - | ||
83 | # HARDCODED CONFIGURATION ##################################################### | 83 | # HARDCODED CONFIGURATION ##################################################### |
84 | 84 | ||
85 | ASTRONOMICAL_UNIT_IN_KM = 1.496e8 | 85 | ASTRONOMICAL_UNIT_IN_KM = 1.496e8 |
@@ -333,6 +333,40 @@ def datetime_from_list(time_list): | @@ -333,6 +333,40 @@ def datetime_from_list(time_list): | ||
333 | "%Y%j%H%M%S%f" | 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 | def get_local_filename(url): | 371 | def get_local_filename(url): |
338 | """ | 372 | """ |
@@ -483,10 +517,6 @@ ORDER BY time_min, granule_gid | @@ -483,10 +517,6 @@ ORDER BY time_min, granule_gid | ||
483 | 'external_link': row[3].text, | 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 | return rows | 521 | return rows |
492 | except Exception as e: | 522 | except Exception as e: |
@@ -654,38 +684,6 @@ def get_data_for_target(target_config, input_slug, | @@ -654,38 +684,6 @@ def get_data_for_target(target_config, input_slug, | ||
654 | # abort(500, "Invalid orbit configuration for '%s' : %s" | 684 | # abort(500, "Invalid orbit configuration for '%s' : %s" |
655 | # % (target_config['slug'], str(e))) | 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 | precision = "%Y-%m-%dT%H" # model and orbits times are only equal-ish | 688 | precision = "%Y-%m-%dT%H" # model and orbits times are only equal-ish |
691 | orbit_data = {} # keys are datetime as str, values arrays of XY | 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,7 +912,6 @@ def generate_csv_file_if_needed(target_slug, input_slug, | ||
914 | if isfile(local_csv_file): | 912 | if isfile(local_csv_file): |
915 | log.warning("Removing failed CSV '%s'..." % local_csv_file) | 913 | log.warning("Removing failed CSV '%s'..." % local_csv_file) |
916 | removefile(local_csv_file) | 914 | removefile(local_csv_file) |
917 | - # pprint(e) | ||
918 | abort(500, "Failed creating CSV '%s' : %s" % (filename, e)) | 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,7 +1520,6 @@ def download_targets_cdf(targets, inp, started_at, stopped_at): | ||
1523 | 1520 | ||
1524 | for param in params: | 1521 | for param in params: |
1525 | k = "%s_%s" % (target_slug, param) | 1522 | k = "%s_%s" % (target_slug, param) |
1526 | - # print("PARAM %s" % k) | ||
1527 | values = [] | 1523 | values = [] |
1528 | i = available_params.index(param) | 1524 | i = available_params.index(param) |
1529 | has_nones = False | 1525 | has_nones = False |
@@ -1603,7 +1599,6 @@ def download_auroral_catalog_csv(target): | @@ -1603,7 +1599,6 @@ def download_auroral_catalog_csv(target): | ||
1603 | # Filter the emissions | 1599 | # Filter the emissions |
1604 | def _keep_emission(emission): | 1600 | def _keep_emission(emission): |
1605 | ok = thumbnail_url_filter.match(emission['thumbnail_url']) | 1601 | ok = thumbnail_url_filter.match(emission['thumbnail_url']) |
1606 | - # print("ok", ok, emission['thumbnail_url']) | ||
1607 | return bool(ok) | 1602 | return bool(ok) |
1608 | 1603 | ||
1609 | emissions = [e for e in emissions if _keep_emission(e)] | 1604 | emissions = [e for e in emissions if _keep_emission(e)] |