test_mn1_rec.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. '''
  2. @author: olivier.massot, janv. 2019
  3. '''
  4. from core import mncheck
  5. import logging
  6. from qgis.core import QgsCoordinateReferenceSystem, QgsGeometry, QgsPointXY
  7. import re
  8. from core.checking import SUCCESS, FAILURE, ERROR
  9. from path import Path
  10. from test._base import SchemaTest
  11. logger = logging.getLogger("mncheck")
  12. class Test(SchemaTest):
  13. SCHEMA_NAME = "mn1_rec"
  14. PROJECT_FILE = Path(__file__).parent / 'projects' / 'mn1_rec' / '1_valid' / '1_valid.qgz'
  15. def setUp(self):
  16. SchemaTest.setUp(self)
  17. self.schema = mncheck.get_schema(self.SCHEMA_NAME)
  18. if not self.schema.checkers:
  19. raise AttributeError("Aucun testeur trouvé dans le schéma")
  20. self.checker = self.schema.checkers[0]()
  21. def run_test(self, test_name, dry=False):
  22. results = self.checker.run(test_name, dry)
  23. if len(results) == 0:
  24. raise Exception("No result for test")
  25. elif len(results) > 1:
  26. raise Exception("More than one result from test")
  27. return results[0]
  28. def assertSuccess(self, r):
  29. if not r.status == SUCCESS:
  30. raise AssertionError("Le test a échoué")
  31. def assertFailure(self, r):
  32. if not r.status == FAILURE:
  33. raise AssertionError("Le test n'aurait pas dû réussir")
  34. def assertError(self, r):
  35. if not r.status == ERROR:
  36. raise AssertionError("Le test n'a pas levé d'erreur")
  37. def assertErrorLogged(self, result, err_msg):
  38. if not any((re.fullmatch(err_msg, err.message) for err in result.errors)):
  39. raise AssertionError("Error was not logged: {}".format(err_msg))
  40. def test_load_layers(self):
  41. # cas initial: valide
  42. r = self.run_test("test_load_layers")
  43. self.assertEqual(r.title, 'Chargement des données')
  44. self.assertSuccess(r)
  45. self.assertEqual(len(r.errors), 0)
  46. # une couche manquante et une pk manquante
  47. _pk_ini = self.schema.Cable.pk
  48. try:
  49. self.schema.Artere.layer = None
  50. self.schema.Cable.pk = "not_a_qgis_field"
  51. r = self.run_test("test_load_layers", True)
  52. self.assertFailure(r)
  53. self.assertErrorLogged(r, ".*Couche manquante.*")
  54. self.assertErrorLogged(r, ".*Clef primaire manquante.*")
  55. finally:
  56. self.schema.Cable.pk = _pk_ini
  57. def test_scr(self):
  58. # cas initial: valide
  59. r = self.run_test("test_scr")
  60. self.assertEqual(r.title, 'Contrôle des projections')
  61. self.assertSuccess(r)
  62. self.assertEqual(len(r.errors), 0)
  63. # mauvaise projection
  64. crs = QgsCoordinateReferenceSystem()
  65. crs.createFromSrid(4473)
  66. self.schema.Artere.layer.setCrs(crs)
  67. r = self.run_test("test_scr", True)
  68. self.assertFailure(r)
  69. self.assertErrorLogged(r, f"Mauvaise projection.*")
  70. def test_structure_arteres(self):
  71. # cas initial: valide
  72. r = self.run_test("test_structure_arteres")
  73. self.assertEqual(r.title, 'Structure des données: Artères')
  74. self.assertSuccess(r)
  75. self.assertEqual(len(r.errors), 0)
  76. # valeur non autorisée
  77. self.checker.arteres[0].AR_ID_INSE = "invalid"
  78. r = self.run_test("test_structure_arteres", True)
  79. self.assertFailure(r)
  80. def test_structure_cables(self):
  81. # cas initial: valide
  82. r = self.run_test("test_structure_cables")
  83. self.assertEqual(r.title, 'Structure des données: Cables')
  84. self.assertSuccess(r)
  85. self.assertEqual(len(r.errors), 0)
  86. # valeur non autorisée
  87. self.checker.cables[0].CA_TYPE = "invalid"
  88. r = self.run_test("test_structure_cables", True)
  89. self.assertFailure(r)
  90. def test_structure_equipements(self):
  91. # cas initial: valide
  92. r = self.run_test("test_structure_equipements")
  93. self.assertEqual(r.title, 'Structure des données: Equipements')
  94. self.assertSuccess(r)
  95. self.assertEqual(len(r.errors), 0)
  96. # valeur non autorisée
  97. self.checker.equipements[0].EQ_TYPE = "invalid"
  98. r = self.run_test("test_structure_equipements", True)
  99. self.assertFailure(r)
  100. def test_structure_noeuds(self):
  101. # cas initial: valide
  102. r = self.run_test("test_structure_noeuds")
  103. self.assertEqual(r.title, 'Structure des données: Noeuds')
  104. self.assertSuccess(r)
  105. self.assertEqual(len(r.errors), 0)
  106. # valeur non autorisée
  107. self.checker.noeuds[0].NO_ID_INSE = "invalid"
  108. r = self.run_test("test_structure_noeuds", True)
  109. self.assertFailure(r)
  110. def test_structure_tranchees(self):
  111. # cas initial: valide
  112. r = self.run_test("test_structure_tranchees")
  113. self.assertEqual(r.title, 'Structure des données: Tranchées')
  114. self.assertSuccess(r)
  115. self.assertEqual(len(r.errors), 0)
  116. # valeur non autorisée
  117. self.checker.tranchees[0].TR_REVET = "invalid"
  118. r = self.run_test("test_structure_tranchees", True)
  119. self.assertFailure(r)
  120. def test_structure_zapbos(self):
  121. # cas initial: valide
  122. r = self.run_test("test_structure_zapbos")
  123. self.assertEqual(r.title, 'Structure des données: Zapbos')
  124. self.assertSuccess(r)
  125. self.assertEqual(len(r.errors), 0)
  126. # valeur non autorisée
  127. self.checker.zapbos[0].STATUT = "invalid"
  128. r = self.run_test("test_structure_zapbos", True)
  129. self.assertFailure(r)
  130. def test_geometry_validity(self):
  131. # cas initial: valide
  132. r = self.run_test("test_geometry_validity")
  133. self.assertEqual(r.title, 'Contrôle de la validité des géométries')
  134. self.assertSuccess(r)
  135. self.assertEqual(len(r.errors), 0)
  136. # géométrie invalide
  137. self.checker.arteres[0]._feature.setGeometry(QgsGeometry())
  138. r = self.run_test("test_geometry_validity", True)
  139. self.assertFailure(r)
  140. self.assertErrorLogged(r, "La géométrie de l'objet est invalide")
  141. def test_geometry_type(self):
  142. # cas initial: valide
  143. r = self.run_test("test_geometry_type")
  144. self.assertEqual(r.title, 'Contrôle des types de géométries')
  145. self.assertSuccess(r)
  146. self.assertEqual(len(r.errors), 0)
  147. # type de géométrie invalide
  148. self.checker.arteres[0]._feature.setGeometry(QgsGeometry())
  149. r = self.run_test("test_geometry_type", True)
  150. self.assertFailure(r)
  151. self.assertErrorLogged(r, "Type de géométrie invalide.*")
  152. def test_bounding_box(self):
  153. # cas initial: valide
  154. r = self.run_test("test_bounding_box")
  155. self.assertEqual(r.title, 'Contrôle des emprises')
  156. self.assertSuccess(r)
  157. self.assertEqual(len(r.errors), 0)
  158. # hors de l'emprise
  159. self.checker.noeuds[0]._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  160. r = self.run_test("test_bounding_box", True)
  161. self.assertFailure(r)
  162. self.assertErrorLogged(r, "Hors de l'emprise autorisée")
  163. def test_duplicates(self):
  164. # cas initial: valide
  165. r = self.run_test("test_duplicates")
  166. self.assertEqual(r.title, 'Recherche de doublons')
  167. self.assertSuccess(r)
  168. self.assertEqual(len(r.errors), 0)
  169. # cas de doublon
  170. self.checker.noeuds[0].NO_NOM = self.checker.noeuds[1].NO_NOM
  171. r = self.run_test("test_duplicates", True)
  172. self.assertFailure(r)
  173. self.assertErrorLogged(r, "Doublons dans le champs NO_NOM")
  174. def test_constraints_arteres_noeuds(self):
  175. # cas initial: valide
  176. r = self.run_test("test_constraints_arteres_noeuds")
  177. self.assertEqual(r.title, 'Application des contraintes: Artères / Noeuds')
  178. self.assertSuccess(r)
  179. self.assertEqual(len(r.errors), 0)
  180. # contrainte invalide
  181. self.checker.arteres[0].noeud_a = None
  182. r = self.run_test("test_constraints_arteres_noeuds", True)
  183. self.assertFailure(r)
  184. self.assertErrorLogged(r, "Le noeud lié '.+' n'existe pas")
  185. def test_constraints_cables_equipements(self):
  186. # cas initial: valide
  187. r = self.run_test("test_constraints_cables_equipements")
  188. self.assertEqual(r.title, 'Application des contraintes: Equipements / Cables')
  189. self.assertSuccess(r)
  190. self.assertEqual(len(r.errors), 0)
  191. # contrainte invalide
  192. self.checker.cables[0].equipement_a = None
  193. r = self.run_test("test_constraints_cables_equipements", True)
  194. self.assertFailure(r)
  195. self.assertErrorLogged(r, "L'équipement lié '.+' n'existe pas*")
  196. def test_constraints_cables_equipements_b(self):
  197. # cas initial: valide
  198. r = self.run_test("test_constraints_cables_equipements_b")
  199. self.assertEqual(r.title, 'Application des contraintes: Equipements B')
  200. self.assertSuccess(r)
  201. self.assertEqual(len(r.errors), 0)
  202. # contrainte invalide
  203. for cable in self.checker.cables:
  204. cable.CA_EQ_B = ""
  205. r = self.run_test("test_constraints_cables_equipements_b", True)
  206. self.assertFailure(r)
  207. self.assertErrorLogged(r, "L'equipement '.+' n'est l'équipement B d'aucun cable.+")
  208. def test_constraints_equipements_noeuds(self):
  209. # cas initial: valide
  210. r = self.run_test("test_constraints_equipements_noeuds")
  211. self.assertEqual(r.title, 'Application des contraintes: Noeuds / Equipements')
  212. self.assertSuccess(r)
  213. self.assertEqual(len(r.errors), 0)
  214. # contrainte invalide
  215. self.checker.equipements[0].noeud = None
  216. r = self.run_test("test_constraints_equipements_noeuds", True)
  217. self.assertFailure(r)
  218. self.assertErrorLogged(r, "Le noeud lié '.+' n'existe pas")
  219. def test_graphic_duplicates(self):
  220. # cas initial: valide
  221. r = self.run_test("test_graphic_duplicates")
  222. self.assertEqual(r.title, 'Recherche de doublons graphiques')
  223. self.assertSuccess(r)
  224. self.assertEqual(len(r.errors), 0)
  225. # doublon graphique
  226. self.checker.noeuds[0]._feature.setGeometry(self.checker.noeuds[1]._feature.geometry())
  227. r = self.run_test("test_graphic_duplicates", True)
  228. self.assertFailure(r)
  229. self.assertErrorLogged(r, "Une entité graphique est dupliquée")
  230. def test_positions_noeuds(self):
  231. # cas initial: valide
  232. r = self.run_test("test_positions_noeuds")
  233. self.assertEqual(r.title, 'Topologie: Noeuds / Artères')
  234. self.assertSuccess(r)
  235. self.assertEqual(len(r.errors), 0)
  236. # erreur topo
  237. self.checker.noeuds[0]._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  238. r = self.run_test("test_positions_noeuds", True)
  239. self.assertFailure(r)
  240. self.assertErrorLogged(r, "Pas de noeud aux coordonnées attendues.*")
  241. def test_positions_equipements(self):
  242. # cas initial: valide
  243. r = self.run_test("test_positions_equipements")
  244. self.assertEqual(r.title, 'Topologie: Equipements / Cables')
  245. self.assertSuccess(r)
  246. self.assertEqual(len(r.errors), 0)
  247. # erreur topo
  248. self.checker.cables[0].equipement_b.noeud._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  249. r = self.run_test("test_positions_equipements", True)
  250. self.assertFailure(r)
  251. self.assertErrorLogged(r, "Pas d'équipement aux coordonnées attendues.*")
  252. def test_tranchee_artere(self):
  253. # cas initial: valide
  254. r = self.run_test("test_tranchee_artere")
  255. self.assertEqual(r.title, 'Topologie: Tranchées / Artères')
  256. self.assertSuccess(r)
  257. self.assertEqual(len(r.errors), 0)
  258. # erreur topo
  259. new_geom = self.checker.tranchees[0]._feature.geometry()
  260. new_geom.translate(10000, 10000)
  261. self.checker.tranchees[0]._feature.setGeometry(new_geom)
  262. r = self.run_test("test_tranchee_artere", True)
  263. self.assertFailure(r)
  264. self.assertErrorLogged(r, "Tranchée ou portion de tranchée sans artère")
  265. def test_cable_artere(self):
  266. # cas initial: valide
  267. r = self.run_test("test_cable_artere")
  268. self.assertEqual(r.title, 'Topologie: Cables / Artères')
  269. self.assertSuccess(r)
  270. self.assertEqual(len(r.errors), 0)
  271. # erreur topo
  272. self.checker.cables[0].CA_COMMENT = ""
  273. new_geom = self.checker.cables[0]._feature.geometry()
  274. new_geom.translate(10000, 10000)
  275. self.checker.cables[0]._feature.setGeometry(new_geom)
  276. r = self.run_test("test_cable_artere", True)
  277. self.assertFailure(r)
  278. self.assertErrorLogged(r, "Cable ou portion de cable sans artère")
  279. def test_artere_cable(self):
  280. # cas initial: valide
  281. r = self.run_test("test_artere_cable")
  282. self.assertEqual(r.title, 'Topologie: Artères / Cables')
  283. self.assertSuccess(r)
  284. self.assertEqual(len(r.errors), 0)
  285. # erreur topo
  286. self.checker.arteres[0].AR_COMMENT = ""
  287. new_geom = self.checker.arteres[0]._feature.geometry()
  288. new_geom.translate(10000, 10000)
  289. self.checker.arteres[0]._feature.setGeometry(new_geom)
  290. r = self.run_test("test_artere_cable", True)
  291. self.assertFailure(r)
  292. self.assertErrorLogged(r, "Artère ou portion d'artère sans cable")
  293. def test_arteres_enterrees(self):
  294. # cas initial: valide
  295. r = self.run_test("test_arteres_enterrees")
  296. self.assertEqual(r.title, 'Données des artères enterrées')
  297. self.assertSuccess(r)
  298. self.assertEqual(len(r.errors), 0)
  299. self.checker.arteres[0].AR_TYPE_FO = "PVC"
  300. del self.checker.arteres[0].__dict__["AR_NB_FOUR"]
  301. self.checker.arteres[0].AR_FOU_DIS = ""
  302. r = self.run_test("test_arteres_enterrees", True)
  303. self.assertFailure(r)
  304. self.assertErrorLogged(r, "Le champs est obligatoire: AR_NB_FOUR")
  305. self.assertErrorLogged(r, "Le champs doit être renseigné: AR_FOU_DIS")
  306. def test_dates_install(self):
  307. """ Dates d'installation
  308. Vérifie que les dates d'installation sont renseignées pour les équipements en service """
  309. # cas initial: valide
  310. r = self.run_test("test_dates_install")
  311. self.assertEqual(r.title, "Dates d'installation")
  312. self.assertSuccess(r)
  313. self.assertEqual(len(r.errors), 0)
  314. self.checker.cables[0].CA_STATUT = "REC"
  315. self.checker.cables[0].CA_DATE_IN = ""
  316. r = self.run_test("test_dates_install", True)
  317. self.assertFailure(r)
  318. self.assertErrorLogged(r, "Date d'installation \(CA_DATE_IN\) manquante")
  319. def test_largeur_tranchees(self):
  320. # cas initial: valide
  321. r = self.run_test("test_largeur_tranchees")
  322. self.assertEqual(r.title, "Tranchées: Dimensions")
  323. self.assertSuccess(r)
  324. self.assertEqual(len(r.errors), 0)
  325. self.checker.tranchees[0].TR_MOD_POS = "TRANCHEE"
  326. self.checker.tranchees[0].TR_LARG = 0
  327. r = self.run_test("test_largeur_tranchees", True)
  328. self.assertFailure(r)
  329. self.assertErrorLogged(r, "La largeur de la tranchée doit être supérieure à 0")
  330. def test_prop_gest(self):
  331. # cas initial: valide
  332. r = self.run_test("test_prop_gest")
  333. self.assertEqual(r.title, "Propriétaires / Gestionnaires")
  334. self.assertSuccess(r)
  335. self.assertEqual(len(r.errors), 0)
  336. self.checker.arteres[0].AR_PRO_FOU = "ORANGE"
  337. self.checker.arteres[0].AR_GEST_FO = "ERDF"
  338. r = self.run_test("test_prop_gest", True)
  339. self.assertFailure(r)
  340. self.assertErrorLogged(r, "Propriétaire: ORANGE, gestionnaire\(s\) possible\(s\): ORANGE \(renseigné: ERDF\)")
  341. def test_comments(self):
  342. # cas initial: valide
  343. r = self.run_test("test_comments")
  344. self.assertEqual(r.title, "Présence de commentaires")
  345. self.assertSuccess(r)
  346. self.assertEqual(len(r.errors), 0)
  347. self.checker.equipements[0].EQ_STATUT = "APD"
  348. self.checker.equipements[0].EQ_COMMENT = ""
  349. r = self.run_test("test_comments", True)
  350. self.assertFailure(r)
  351. self.assertErrorLogged(r, "L'equipement n'est pas en REC, un commentaire devrait en préciser la raison")
  352. def test_dimensions_fourreaux(self):
  353. # cas initial: valide
  354. r = self.run_test("test_dimensions_fourreaux")
  355. self.assertEqual(r.title, 'Dimensions logiques: fourreaux')
  356. self.assertSuccess(r)
  357. self.assertEqual(len(r.errors), 0)
  358. # nombre de fourreaux incohérent
  359. self.checker.arteres[0].AR_FOU_DIS = 1000
  360. r = self.run_test("test_dimensions_fourreaux", True)
  361. self.assertFailure(r)
  362. self.assertErrorLogged(r, "Le nombre de fourreaux disponibles \(AR_FOU_DIS\) doit être inférieur au nombre total \(AR_NB_FOUR\)")
  363. self.checker.arteres[0].AR_FOU_DIS = 0
  364. # nombre de fourreaux incohérent
  365. self.checker.cables[0].CA_NB_FO_U = 1000
  366. r = self.run_test("test_dimensions_fourreaux", True)
  367. self.assertFailure(r)
  368. self.assertErrorLogged(r, "Le nombre de fourreaux utilisés \(CA_NB_FO_U\) doit être inférieur au nombre total \(CA_NB_FO\)")
  369. self.checker.cables[0].CA_NB_FO_U = 0
  370. # nombre de fourreaux incohérent
  371. self.checker.cables[0].CA_NB_FO_D = 1000
  372. r = self.run_test("test_dimensions_fourreaux", True)
  373. self.assertFailure(r)
  374. self.assertErrorLogged(r, "Le nombre de fourreaux disponibles \(CA_NB_FO_D\) doit être inférieur au nombre total \(CA_NB_FO\)")
  375. def test_pbos(self):
  376. # cas initial: valide
  377. r = self.run_test("test_pbos")
  378. self.assertEqual(r.title, 'Topologie: PBO / ZAPBO')
  379. self.assertSuccess(r)
  380. self.assertEqual(len(r.errors), 0)
  381. # noms equipement / zapbo incoherents
  382. eq = next(e for e in self.checker.equipements if e.EQ_TYPE == "PBO")
  383. eq.EQ_NOM = "babidiboo"
  384. r = self.run_test("test_pbos", True)
  385. self.assertFailure(r)
  386. self.assertErrorLogged(r, "Le nom de la PBO ne coincide avec le nom d'aucune des ZAPBO qui le contiennent")
  387. # equipement hors zapbo
  388. _ini_geom = eq.noeud._feature.geometry()
  389. eq.noeud._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  390. r = self.run_test("test_pbos", True)
  391. self.assertFailure(r)
  392. self.assertErrorLogged(r, "Le PBO n'est contenu dans aucune ZAPBO")
  393. def test_zapbos_prises(self):
  394. # cas initial: valide
  395. r = self.run_test("test_zapbos_prises")
  396. self.assertEqual(r.title, 'Topologie: Zapbos / Prises')
  397. self.assertSuccess(r)
  398. self.assertEqual(len(r.errors), 0)
  399. # pas de prise dans la zapbo
  400. new_geom = self.checker.zapbos[0]._feature.geometry()
  401. new_geom.translate(1000,1000)
  402. self.checker.zapbos[0]._feature.setGeometry(new_geom)
  403. r = self.run_test("test_zapbos_prises", True)
  404. self.assertFailure(r)
  405. self.assertErrorLogged(r, "La Zapbo ne contient aucune prise")
  406. # couche non chargée
  407. self.schema.Prise.layer = None
  408. r = self.run_test("test_zapbos_prises", True)
  409. self.assertError(r)
  410. self.assertErrorLogged(r, "La couche des prises n'est pas chargée")
  411. def test_pbo_dimension(self):
  412. # cas initial: valide
  413. r = self.run_test("test_pbo_dimension")
  414. self.assertEqual(r.title, 'Dimensionnement des PBO')
  415. self.assertSuccess(r)
  416. self.assertEqual(len(r.errors), 0)
  417. # couche non chargée
  418. self.schema.Prise.layer = None
  419. r = self.run_test("test_pbo_dimension", True)
  420. self.assertError(r)
  421. self.assertErrorLogged(r, "La couche des prises n'est pas chargée")