Coverage for pySDC/helpers/testing.py: 100%
30 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 14:51 +0000
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 14:51 +0000
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4Created on Fri Feb 9 14:41:43 2024
6Helpers module for testing utilities
7"""
8import os
9import json
10import warnings
11import numpy as np
14class DataChecker:
15 """
16 Object allowing to quickly generate and check generated data from scripts.
18 Here is an example of use for one given script:
20 >>> from pySDC.helpers.testing import DataChecker
21 >>>
22 >>> data = DataChecker(__file__)
23 >>> # ... some computations ...
24 >>> data.storeAndCheck('solution', solution)
25 >>> # ... some other computations ...
26 >>> data.storeAndCheck('errors', errors)
27 >>> # ... ploting some figures
28 >>> data.writeToJSON() # end of script
30 The `storeAndCheck` method use a unique key as first argument, and the
31 data as second argument, into list format.
32 Calling this method will store the data into a cache variable, and compare
33 with reference data stored in `_dataRef.json` (if it exists, see below ...).
34 Finally, the `writeToJSON` method saves the cache variable into a json
35 file `_data.json`.
37 When there is no `_dataRef.json` in the script directory,
38 executing the script output some warning telling that there is no
39 reference data to compare with.
40 To remove those warnings (and properly test data), just rename the
41 `_data.json` into `_dataRef.json`.
42 Then re-running the script will then compare the newly generated data with
43 the reference data stored into `_dataRef.json`, and raise an error if there
44 is some differences.
46 Important
47 ---------
49 - using the `__file__` built-in variable is necessary to save data in the
50 script directory, independently of the working directory.
51 - several script in the same directory can use the DataChecker, which
52 implies that the key provided to `storeAndCheck` must be unique across
53 all directory scripts. If not, the same key from previous directory will
54 simply be overwritten in the cached variable and the `_data.ref` file.
55 """
57 def __init__(self, filePath):
58 path = '/' + os.path.join(*filePath.split('/')[:-1])
59 self._data = {} # cache for data
60 self._dataRef = None # cache for reference data
61 self._dataFile = os.path.join(path, '_data.json')
62 self._dataRefFile = os.path.join(path, '_dataRef.json')
64 def storeAndCheck(self, key, data, rtol=1e-5, atol=1e-8):
65 """
66 Store data into cache, and check with eventual reference data
68 Parameters
69 ----------
70 key : str
71 Unique key (project wide) for the data.
72 data : list or array-like
73 The data that has to be stored.
74 rtol : float
75 Relative tolerance
76 atol : float
77 Absolute tolerance
78 """
79 self._data[key] = list(data)
80 if self._dataRef is None:
81 try:
82 with open(self._dataRefFile, "r") as f:
83 self._dataRef = json.load(f)
84 except FileNotFoundError:
85 warnings.warn(f"no reference data to check key:{key}")
86 return # pragma: no cover
88 assert key in self._dataRef, f"key:{key} not in reference data"
90 data = self._data[key]
91 ref = self._dataRef[key]
93 assert len(data) == len(ref), f"data with len:{len(data)}) cannot be compared to ref with len:{len(ref)})"
94 assert np.allclose(
95 data, ref, atol=atol, rtol=rtol, equal_nan=True
96 ), f"{key}, difference between data:{data} and ref:{ref}"
98 def writeToJSON(self):
99 """Write cached data into a json file"""
100 if os.path.isfile(self._dataFile):
101 with open(self._dataFile, "r") as f:
102 self._data.update(json.load(f))
103 with open(self._dataFile, "w") as f:
104 json.dump(self._data, f)