import colored import config import inspect import simulation.devices as devices import time DT_TOGGLE = 0.3 TEST_FULL = 'full' TEST_SMOKE = 'smoke' # COLOR_SUCCESS = colored.fg("light_green") COLOR_FAIL = colored.fg("light_red") class test_smarthome(object): def __init__(self, rooms): # add testcases for switching devices for name in rooms.getmembers(): obj = rooms.getobjbyname(name) if obj.__class__.__name__ == "videv_light": common_name = '.'.join(name.split('.')[:-1]) + '.' + name.split('.')[-1][6:] try: li_device = rooms.getobjbyname(common_name + '_zigbee') if obj.enable_brightness or obj.enable_color_temp else None except AttributeError: li_device = rooms.getobjbyname(common_name + '_zigbee_1') if obj.enable_brightness or obj.enable_color_temp else None try: sw_device = rooms.getobjbyname(common_name) if obj.enable_state else None except AttributeError: # must be a device without switching device sw_device = li_device setattr(self, common_name.replace('.', '_'), testcase_light(obj, sw_device, li_device)) # add testcases for heating devices for name in rooms.getmembers(): obj = rooms.getobjbyname(name) if obj.__class__.__name__ == "videv_heating": common_name = '.'.join(name.split('.')[:-1]) + '.' + name.split('.')[-1][6:] heat_device = rooms.getobjbyname(common_name + '_valve') setattr(self, common_name.replace('.', '_'), testcase_heating(obj, heat_device)) # synchronisation self.gfw_dirk_cd_player_amplifier_sync = testcase_synchronisation( rooms.gfw.dirk.cd_player, None, None, rooms.gfw.dirk.amplifier) self.gfw_floor_main_light_sync = testcase_synchronisation( rooms.gfw.floor.main_light, rooms.gfw.floor.videv_main_light, rooms.gfw.floor.videv_main_light, rooms.gfw.floor.main_light_zigbee_1, rooms.gfw.floor.main_light_zigbee_2 ) self.ffe_diningroom_main_light_floor_lamp_sync = testcase_synchronisation( rooms.ffe.diningroom.main_light, None, None, rooms.ffe.diningroom.floor_lamp) self.ffe_livingroom_main_light_floor_lamp_sync = testcase_synchronisation( rooms.ffe.livingroom.main_light, rooms.ffe.livingroom.videv_floor_lamp, rooms.ffe.livingroom.videv_floor_lamp, *[getattr(rooms.ffe.livingroom, "floor_lamp_zigbee_%d" % i) for i in range(1, 7)] ) # add test collection self.all = test_collection(self) def getmembers(self, prefix=''): rv = [] for name, obj in inspect.getmembers(self): if prefix: full_name = prefix + '.' + name else: full_name = name if not name.startswith('_'): try: if obj.__class__.__bases__[0].__name__ == "testcase" or obj.__class__.__name__ == "test_collection": rv.append(full_name) else: rv.extend(obj.getmembers(full_name)) except AttributeError: pass return rv def getobjbyname(self, name): if name.startswith("test."): name = name[5:] obj = self for subname in name.split('.'): obj = getattr(obj, subname) return obj def command(self, full_command): try: parameter = " " + full_command.split(' ')[1] except IndexError: parameter = "" command = full_command.split(' ')[0].split('.')[-1] + parameter device_name = '.'.join(full_command.split(' ')[0].split('.')[:-1]) self.getobjbyname(device_name).command(command) class test_result_base(object): def __init__(self): self.__init_test_counters__() def __init_test_counters__(self): self.test_counter = 0 self.success_tests = 0 self.failed_tests = 0 def statistic(self): return (self.test_counter, self.success_tests, self.failed_tests) def print_statistic(self): color = COLOR_SUCCESS if self.test_counter == self.success_tests else COLOR_FAIL print(color + "*** SUCCESS: (%4d/%4d) FAIL: (%4d/%4d) ***\n" % (self.success_tests, self.test_counter, self.failed_tests, self.test_counter) + colored.attr("reset")) class test_collection(test_result_base): def __init__(self, test_instance): super().__init__() self.test_instance = test_instance def capabilities(self): return [TEST_FULL, TEST_SMOKE] def command(self, command): self.__init_test_counters__() for member in self.test_instance.getmembers(): obj = self.test_instance.getobjbyname(member) if id(obj) != id(self): obj.test_all(command) num, suc, fail = obj.statistic() self.test_counter += num self.success_tests += suc self.failed_tests += fail self.print_statistic() class testcase(test_result_base): def __init__(self): super().__init__() self.__test_list__ = [] def capabilities(self): if len(self.__test_list__) > 0 and not 'test_all' in self.__test_list__: self.__test_list__.append('test_all') self.__test_list__.sort() return self.__test_list__ def test_all(self, test=TEST_FULL): test_counter = 0 success_tests = 0 failed_tests = 0 for tc_name in self.capabilities(): if tc_name != "test_all": self.command(tc_name, test) test_counter += self.test_counter success_tests += self.success_tests failed_tests += self.failed_tests self.test_counter = test_counter self.success_tests = success_tests self.failed_tests = failed_tests def command(self, command, test=TEST_FULL): self.__init_test_counters__() tc = getattr(self, command) self.__init_test_counters__() tc(test) self.print_statistic() def heading(self, desciption): print(desciption) def sub_heading(self, desciption): print(2 * " " + desciption) def result(self, desciption, success): self.test_counter += 1 if success: self.success_tests += 1 else: self.failed_tests += 1 print(4 * " " + ("SUCCESS - " if success else "FAIL - ") + desciption) class testcase_light(testcase): def __init__(self, videv, sw_device, li_device): self.videv = videv self.sw_device = sw_device self.li_device = li_device self.__test_list__ = [] if self.videv.enable_state: self.__test_list__.append('test_power_on_off') if self.videv.enable_brightness: self.__test_list__.append('test_brightness') if self.videv.enable_color_temp: self.__test_list__.append('test_color_temp') def test_power_on_off(self, test=TEST_FULL): self.heading("Power On/ Off test (%s)" % self.videv.topic) # sw_state = self.sw_device.get(self.sw_device.KEY_OUTPUT_0) # for i in range(0, 2): self.sub_heading("State change of switching device") # self.sw_device.set(self.sw_device.KEY_OUTPUT_0, not self.sw_device.get(self.sw_device.KEY_OUTPUT_0)) time.sleep(DT_TOGGLE) self.result("Virtual device state after Switch on by switching device", sw_state != self.videv.get(self.videv.KEY_OUTPUT_0)) self.result("Switching device state after Switch on by switching device", sw_state != self.sw_device.get(self.sw_device.KEY_OUTPUT_0)) self.sub_heading("State change of virtual device") # self.videv.set(self.videv.KEY_OUTPUT_0, not self.videv.get(self.videv.KEY_OUTPUT_0)) time.sleep(DT_TOGGLE) self.result("Virtual device state after Switch off by virtual device", sw_state == self.videv.get(self.videv.KEY_OUTPUT_0)) self.result("Switching device state after Switch on by switching device", sw_state == self.sw_device.get(self.sw_device.KEY_OUTPUT_0)) def test_brightness(self, test=TEST_FULL): self.heading("Brightness test (%s)" % self.videv.topic) # br_state = self.li_device.get(self.li_device.KEY_BRIGHTNESS) delta = -15 if br_state > 50 else 15 self.sw_device.set(self.sw_device.KEY_OUTPUT_0, True) time.sleep(DT_TOGGLE) for i in range(0, 2): self.sub_heading("Brightness change by light device") # self.li_device.set(self.li_device.KEY_BRIGHTNESS, br_state + delta) time.sleep(DT_TOGGLE) self.result("Virtual device state after setting brightness by light device", br_state + delta == self.videv.get(self.videv.KEY_BRIGHTNESS)) self.result("Light device state after setting brightness by light device", br_state + delta == self.li_device.get(self.li_device.KEY_BRIGHTNESS)) self.sub_heading("Brightness change by virtual device") # self.videv.set(self.videv.KEY_BRIGHTNESS, br_state) time.sleep(DT_TOGGLE) self.result("Virtual device state after setting brightness by light device", br_state == self.videv.get(self.videv.KEY_BRIGHTNESS)) self.result("Light device state after setting brightness by light device", br_state == self.li_device.get(self.li_device.KEY_BRIGHTNESS)) self.sw_device.set(self.sw_device.KEY_OUTPUT_0, False) time.sleep(DT_TOGGLE) def test_color_temp(self, test=TEST_FULL): self.heading("Color temperature test (%s)" % self.videv.topic) # ct_state = self.li_device.get(self.li_device.KEY_COLOR_TEMP) delta = -3 if ct_state > 5 else 3 self.sw_device.set(self.sw_device.KEY_OUTPUT_0, True) time.sleep(DT_TOGGLE) for i in range(0, 2): self.sub_heading("Color temperature change by light device") # self.li_device.set(self.li_device.KEY_COLOR_TEMP, ct_state + delta) time.sleep(DT_TOGGLE) self.result("Virtual device state after setting color temperature by light device", ct_state + delta == self.videv.get(self.videv.KEY_COLOR_TEMP)) self.result("Light device state after setting color temperature by light device", ct_state + delta == self.li_device.get(self.li_device.KEY_COLOR_TEMP)) self.sub_heading("Color temperature change by virtual device") # self.videv.set(self.videv.KEY_COLOR_TEMP, ct_state) time.sleep(DT_TOGGLE) self.result("Virtual device state after setting color temperature by light device", ct_state == self.videv.get(self.videv.KEY_COLOR_TEMP)) self.result("Light device state after setting color temperature by light device", ct_state == self.li_device.get(self.li_device.KEY_COLOR_TEMP)) self.sw_device.set(self.sw_device.KEY_OUTPUT_0, False) time.sleep(DT_TOGGLE) class testcase_synchronisation(testcase): def __init__(self, sw_master, br_master, ct_master, *follower): super().__init__() self.sw_master = sw_master self.br_master = br_master self.ct_master = ct_master self.follower = follower self.__test_list__ = [] if sw_master is not None: self.__test_list__.append('test_power_on_off_sync') if br_master is not None: self.__test_list__.append('test_brightness_sync') def test_power_on_off_sync(self, test=TEST_FULL): self.heading("Power On/ Off sychronisation test") # # set sw_master to slave state as precondition f_state = self.follower[0].get(self.follower[0].KEY_OUTPUT_0) self.sw_master.set(self.sw_master.KEY_OUTPUT_0, f_state) time.sleep(DT_TOGGLE) for i in range(0, 2): self.sub_heading("State change of sw_master device") # self.sw_master.set(self.sw_master.KEY_OUTPUT_0, not f_state) time.sleep(DT_TOGGLE) f_state = not f_state for fo in self.follower: self.result("Follower device state after switching (%s)" % fo.topic, f_state == fo.get(fo.KEY_OUTPUT_0)) def test_brightness_sync(self, test=TEST_FULL): self.heading("Power On/ Off sychronisation test") # # set precondition sw_state = self.sw_master.get(self.sw_master.KEY_OUTPUT_0) self.sw_master.set(self.sw_master.KEY_OUTPUT_0, True) time.sleep(DT_TOGGLE) target = self.follower[0].get(self.follower[0].KEY_BRIGHTNESS) delta = 15 if target < 50 else -15 for i in range(0, 2): target = target + delta self.sub_heading("State change of br_master device") # self.br_master.set(self.br_master.KEY_BRIGHTNESS, target) time.sleep(DT_TOGGLE) for fo in self.follower: self.result("Follower device brightness after change (%s)" % fo.topic, target == fo.get(fo.KEY_BRIGHTNESS)) delta = -delta # reset changes of precondition self.sw_master.set(self.sw_master.KEY_OUTPUT_0, sw_state) time.sleep(DT_TOGGLE) class testcase_heating(testcase): def __init__(self, videv, valve): self.__videv__ = videv self.__valve__ = valve self.__default_temperature__ = config.DEFAULT_TEMPERATURE.get(self.__valve__.topic) self.__test_list__ = ["test_user_temperature_setpoint", "test_default_temperature", ] def test_user_temperature_setpoint(self, test=TEST_FULL): self.heading("User temperature setpoint test (%s)" % self.__videv__.topic) # mtemp = round(self.__valve__.TEMP_RANGE[0] + (self.__valve__.TEMP_RANGE[1] - self.__valve__.TEMP_RANGE[0]) / 2, 1) setp = self.__valve__.get(self.__valve__.KEY_TEMPERATURE_SETPOINT) delta = 5 if setp < mtemp else -5 for i in range(0, 2): self.sub_heading("Setpoint change by valve device") # self.__valve__.set(self.__valve__.KEY_TEMPERATURE_SETPOINT, setp + delta) time.sleep(DT_TOGGLE) self.result("Virtual device valve temperature after setting temperature by valve device", setp + delta == self.__videv__.get(self.__videv__.KEY_VALVE_TEMPERATURE_SETPOINT)) self.result("Virtual device user temperature after setting temperature by valve device", setp + delta == self.__videv__.get(self.__videv__.KEY_USER_TEMPERATURE_SETPOINT)) self.sub_heading("Setpoint change by videv device") # self.__videv__.set(self.__videv__.KEY_USER_TEMPERATURE_SETPOINT, setp) time.sleep(DT_TOGGLE) self.result("Valve device temperature setpoint after setting temperature by videv device", setp == self.__valve__.get(self.__valve__.KEY_TEMPERATURE_SETPOINT)) self.result("Virtual device valve temperature after setting temperature by videv device", setp == self.__videv__.get(self.__videv__.KEY_VALVE_TEMPERATURE_SETPOINT)) def test_default_temperature(self, test=TEST_FULL): self.heading("Default temperature setpoint test (%s)" % self.__videv__.topic) # dtemp = config.DEFAULT_TEMPERATURE.get(self.__valve__.topic) mtemp = round(self.__valve__.TEMP_RANGE[0] + (self.__valve__.TEMP_RANGE[1] - self.__valve__.TEMP_RANGE[0]) / 2, 1) ptemp = dtemp + (5 if dtemp < mtemp else -5) self.sub_heading("Setting setpoint to a value unequal default as precondition") self.__valve__.set(self.__valve__.KEY_TEMPERATURE_SETPOINT, ptemp) time.sleep(DT_TOGGLE) self.result("Valve device temperature setpoint after setting precondition temperature", ptemp == self.__valve__.get(self.__valve__.KEY_TEMPERATURE_SETPOINT)) self.sub_heading("Triggering default temperature by videv device") self.__videv__.set(self.__videv__.KEY_SET_DEFAULT_TEMPERATURE, None) time.sleep(DT_TOGGLE) self.result("Valve device temperature setpoint after setting default temperature", dtemp == self.__valve__.get(self.__valve__.KEY_TEMPERATURE_SETPOINT)) def test_summer_mode(self, test=TEST_FULL): pass def test_away_mode(self, test=TEST_FULL): pass def test_boost_mode(self, test=TEST_FULL): pass if test == TEST_FULL: # test boost timer pass