conftest.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. from __future__ import annotations
  2. from datetime import timedelta
  3. import numpy as np
  4. import pandas as pd
  5. import pytest
  6. from flask_security import SQLAlchemySessionUserDatastore, hash_password
  7. from sqlalchemy import select, delete
  8. from flexmeasures import Sensor, Source, User, UserRole
  9. from flexmeasures.data.models.data_sources import DataSource
  10. from flexmeasures.data.models.generic_assets import GenericAssetType, GenericAsset
  11. from flexmeasures.data.models.time_series import TimedBelief
  12. @pytest.fixture(scope="module")
  13. def setup_api_test_data(
  14. db, setup_roles_users, setup_generic_assets
  15. ) -> dict[str, Sensor]:
  16. """
  17. Set up data for API v3.0 tests.
  18. """
  19. print("Setting up data for API v3.0 tests on %s" % db.engine)
  20. sensors = add_incineration_line(
  21. db, db.session.get(User, setup_roles_users["Test Supplier User"])
  22. )
  23. return sensors
  24. @pytest.fixture(scope="function")
  25. def setup_api_fresh_test_data(
  26. fresh_db, setup_roles_users_fresh_db, setup_generic_assets_fresh_db
  27. ):
  28. """
  29. Set up fresh data for API dev tests.
  30. """
  31. print("Setting up fresh data for API 3.0 tests on %s" % fresh_db.engine)
  32. for sensor in fresh_db.session.scalars(select(Sensor)).all():
  33. fresh_db.session.execute(delete(Sensor).filter_by(id=sensor.id))
  34. sensors = add_incineration_line(
  35. fresh_db,
  36. fresh_db.session.get(User, setup_roles_users_fresh_db["Test Supplier User"]),
  37. )
  38. return sensors
  39. @pytest.fixture(scope="module")
  40. def setup_inactive_user(db, setup_accounts, setup_roles_users):
  41. """
  42. Set up one inactive user and one inactive admin.
  43. """
  44. add_inactive_users(db, setup_accounts)
  45. @pytest.fixture(scope="function")
  46. def setup_inactive_user_fresh_db(
  47. fresh_db, setup_accounts_fresh_db, setup_roles_users_fresh_db
  48. ):
  49. """
  50. Set up one inactive user and one inactive admin.
  51. """
  52. add_inactive_users(fresh_db, setup_accounts_fresh_db)
  53. def add_inactive_users(db, setup_accounts):
  54. user_datastore = SQLAlchemySessionUserDatastore(db.session, User, UserRole)
  55. user_datastore.create_user(
  56. username="inactive test user",
  57. email="inactive_user@seita.nl",
  58. password=hash_password("testtest"),
  59. account_id=setup_accounts["Prosumer"].id,
  60. active=False,
  61. )
  62. admin = user_datastore.create_user(
  63. username="inactive test admin",
  64. email="inactive_admin@seita.nl",
  65. password=hash_password("testtest"),
  66. account_id=setup_accounts["Prosumer"].id,
  67. active=False,
  68. )
  69. role = user_datastore.find_role("admin")
  70. user_datastore.add_role_to_user(admin, role)
  71. @pytest.fixture(scope="function")
  72. def setup_user_without_data_source(
  73. fresh_db, setup_accounts_fresh_db, setup_roles_users_fresh_db
  74. ) -> User:
  75. """
  76. Set up one user directly without setting up a corresponding data source.
  77. """
  78. user_datastore = SQLAlchemySessionUserDatastore(fresh_db.session, User, UserRole)
  79. user = user_datastore.create_user(
  80. username="test admin with improper registration as a data source",
  81. email="improper_user@seita.nl",
  82. password=hash_password("testtest"),
  83. account_id=setup_accounts_fresh_db["Prosumer"].id,
  84. active=True,
  85. )
  86. role = user_datastore.find_role("admin")
  87. user_datastore.add_role_to_user(user, role)
  88. return user
  89. @pytest.fixture(scope="function")
  90. def keep_scheduling_queue_empty(app):
  91. app.queues["scheduling"].empty()
  92. yield
  93. app.queues["scheduling"].empty()
  94. @pytest.fixture(scope="module")
  95. def add_asset_with_children(db, setup_roles_users):
  96. test_supplier_user = setup_roles_users["Test Supplier User"]
  97. parent_type = GenericAssetType(
  98. name="parent",
  99. )
  100. child_type = GenericAssetType(name="child")
  101. db.session.add_all([parent_type, child_type])
  102. parent = GenericAsset(
  103. name="parent",
  104. generic_asset_type=parent_type,
  105. account_id=test_supplier_user,
  106. )
  107. db.session.add(parent)
  108. db.session.flush() # assign parent asset id
  109. assets = [
  110. GenericAsset(
  111. name=f"child_{i}",
  112. generic_asset_type=child_type,
  113. parent_asset_id=parent.id,
  114. account_id=test_supplier_user,
  115. )
  116. for i in range(1, 3)
  117. ]
  118. db.session.add_all(assets)
  119. db.session.flush() # assign children asset ids
  120. assets.append(parent)
  121. return {a.name: a for a in assets}
  122. def add_incineration_line(db, test_supplier_user) -> dict[str, Sensor]:
  123. incineration_type = GenericAssetType(
  124. name="waste incinerator",
  125. )
  126. db.session.add(incineration_type)
  127. incineration_asset = GenericAsset(
  128. name="incineration line",
  129. generic_asset_type=incineration_type,
  130. owner=test_supplier_user.account,
  131. )
  132. db.session.add(incineration_asset)
  133. gas_sensor = Sensor(
  134. name="some gas sensor",
  135. unit="m³/h",
  136. event_resolution=timedelta(minutes=10),
  137. generic_asset=incineration_asset,
  138. )
  139. db.session.add(gas_sensor)
  140. add_gas_measurements(db, test_supplier_user.data_source[0], gas_sensor)
  141. other_source = DataSource(name="Other source", type="demo script")
  142. db.session.add(other_source)
  143. db.session.flush()
  144. add_gas_measurements(db, other_source, gas_sensor, values=[91.3, np.nan, 92.1])
  145. temperature_sensor = Sensor(
  146. name="some temperature sensor",
  147. unit="°C",
  148. event_resolution=timedelta(0),
  149. generic_asset=incineration_asset,
  150. )
  151. db.session.add(temperature_sensor)
  152. add_temperature_measurements(
  153. db, test_supplier_user.data_source[0], temperature_sensor
  154. )
  155. empty_temperature_sensor = Sensor(
  156. name="empty temperature sensor",
  157. unit="°C",
  158. event_resolution=timedelta(0),
  159. generic_asset=incineration_asset,
  160. )
  161. db.session.add(empty_temperature_sensor)
  162. db.session.flush() # assign sensor ids
  163. return {
  164. gas_sensor.name: gas_sensor,
  165. temperature_sensor.name: temperature_sensor,
  166. empty_temperature_sensor.name: empty_temperature_sensor,
  167. }
  168. def add_gas_measurements(db, source: Source, sensor: Sensor, values=None):
  169. event_starts = [
  170. pd.Timestamp("2021-05-02T00:00:00+02:00") + timedelta(minutes=minutes)
  171. for minutes in range(0, 30, 10)
  172. ]
  173. event_values = list(values) if values else [91.3, 91.7, 92.1]
  174. beliefs = [
  175. TimedBelief(
  176. sensor=sensor,
  177. source=source,
  178. event_start=event_start,
  179. belief_horizon=timedelta(0),
  180. event_value=event_value,
  181. )
  182. for event_start, event_value in zip(event_starts, event_values)
  183. ]
  184. db.session.add_all(beliefs)
  185. def add_temperature_measurements(db, source: Source, sensor: Sensor):
  186. event_starts = [
  187. pd.Timestamp("2021-05-02T00:00:00+02:00") + timedelta(minutes=minutes)
  188. for minutes in range(0, 30, 10)
  189. ]
  190. event_values = [815, 817, 818]
  191. beliefs = [
  192. TimedBelief(
  193. sensor=sensor,
  194. source=source,
  195. event_start=event_start,
  196. belief_horizon=timedelta(0),
  197. event_value=event_value,
  198. )
  199. for event_start, event_value in zip(event_starts, event_values)
  200. ]
  201. db.session.add_all(beliefs)