#!/usr/bin/env python3 """Tests fuer die zur Laufzeit aenderbaren Einstellungen (settings.json). python3 -m unittest -v test_settings Schwerpunkt ist die Pruefung der Werte: Sobald MQTT dazukommt, kommen sie von aussen. Ein Helligkeitswert von 500 % oder eine kaputte Datei darf die Anzeige nicht lahmlegen. """ import json import os import unittest import settings class Tempdatei(unittest.TestCase): def setUp(self): self.pfad = "test_settings_tmp.json" self._weg() def tearDown(self): self._weg() def _weg(self): try: os.remove(self.pfad) except OSError: pass def _schreibe_roh(self, inhalt): with open(self.pfad, "w") as f: f.write(inhalt) class TestLaden(Tempdatei): def test_ohne_datei_gelten_die_vorgaben(self): self.assertEqual(settings.load(self.pfad), settings.DEFAULTS) def test_fehlende_werte_werden_ergaenzt(self): self._schreibe_roh(json.dumps({"schwelle": 1234})) w = settings.load(self.pfad) self.assertEqual(w["schwelle"], 1234) self.assertEqual(w["hell_prozent"], settings.DEFAULTS["hell_prozent"]) def test_kaputtes_json_faellt_auf_die_vorgaben_zurueck(self): """Ein Geraet in der Sternwarte darf daran nicht haengenbleiben.""" self._schreibe_roh("{das ist kein json") self.assertEqual(settings.load(self.pfad), settings.DEFAULTS) def test_json_das_kein_objekt_ist(self): self._schreibe_roh("[1, 2, 3]") self.assertEqual(settings.load(self.pfad), settings.DEFAULTS) def test_einzelner_unbrauchbarer_wert_verwirft_nur_diesen(self): self._schreibe_roh(json.dumps({"schwelle": 99999, "hell_prozent": 42})) meldungen = [] w = settings.load(self.pfad, log=meldungen.append) self.assertEqual(w["schwelle"], settings.DEFAULTS["schwelle"]) # verworfen self.assertEqual(w["hell_prozent"], 42) # uebernommen self.assertTrue(any("schwelle" in m for m in meldungen)) def test_unbekannter_schluessel_wird_ignoriert(self): self._schreibe_roh(json.dumps({"voellig_unbekannt": 1})) w = settings.load(self.pfad) self.assertEqual(w, settings.DEFAULTS) self.assertNotIn("voellig_unbekannt", w) class TestSpeichern(Tempdatei): def test_speichern_und_wieder_lesen(self): settings.save({"schwelle": 2000, "dunkel_prozent": 3}, self.pfad) w = settings.load(self.pfad) self.assertEqual(w["schwelle"], 2000) self.assertEqual(w["dunkel_prozent"], 3) def test_gespeichert_wird_immer_vollstaendig(self): settings.save({"schwelle": 2000}, self.pfad) with open(self.pfad) as f: roh = json.load(f) self.assertEqual(set(roh), set(settings.DEFAULTS)) def test_update_aendert_nur_das_angegebene(self): settings.save({"schwelle": 1000, "hell_prozent": 30}, self.pfad) settings.update({"hell_prozent": 70}, self.pfad) w = settings.load(self.pfad) self.assertEqual(w["hell_prozent"], 70) self.assertEqual(w["schwelle"], 1000) # unveraendert def test_ungueltiges_update_laesst_die_datei_unberuehrt(self): settings.save({"schwelle": 1000}, self.pfad) with self.assertRaises(settings.SettingsError): settings.update({"hell_prozent": 500}, self.pfad) self.assertEqual(settings.load(self.pfad)["schwelle"], 1000) class TestPruefung(unittest.TestCase): """Die Grenzen, an denen spaeter MQTT-Eingaben haengenbleiben sollen.""" def test_prozent_ueber_100_wird_abgelehnt(self): with self.assertRaises(settings.SettingsError): settings.save({"hell_prozent": 101}, "/dev/null") def test_negative_werte_werden_abgelehnt(self): with self.assertRaises(settings.SettingsError): settings.save({"schwelle": -1}, "/dev/null") def test_schwelle_ueber_adc_bereich_wird_abgelehnt(self): with self.assertRaises(settings.SettingsError): settings.save({"schwelle": 4096}, "/dev/null") def test_unbekannter_name_wird_abgelehnt(self): with self.assertRaises(settings.SettingsError): settings.save({"gibtsnicht": 1}, "/dev/null") def test_nichtganzzahlige_werte_werden_abgelehnt(self): for wert in (1.5, "50", None, True): with self.assertRaises(settings.SettingsError): settings.save({"hell_prozent": wert}, "/dev/null") def test_die_raender_sind_erlaubt(self): geprueft = settings._pruefe({"hell_prozent": 100, "dunkel_prozent": 0, "schwelle": 4095, "hysterese": 0}) self.assertEqual(geprueft["hell_prozent"], 100) self.assertEqual(geprueft["schwelle"], 4095) if __name__ == "__main__": unittest.main(verbosity=2)