andrej@1808: #!/usr/bin/env python andrej@1808: # -*- coding: utf-8 -*- andrej@1808: andrej@1808: # This file is part of Beremiz, a Integrated Development Environment for andrej@1808: # programming IEC 61131-3 automates supporting plcopen standard and CanFestival. andrej@1808: # andrej@1808: # Copyright (C) 2017: Andrey Skvortsov andrej@1808: # andrej@1808: # See COPYING file for copyrights details. andrej@1808: # andrej@1808: # This program is free software; you can redistribute it and/or andrej@1808: # modify it under the terms of the GNU General Public License andrej@1808: # as published by the Free Software Foundation; either version 2 andrej@1808: # of the License, or (at your option) any later version. andrej@1808: # andrej@1808: # This program is distributed in the hope that it will be useful, andrej@1808: # but WITHOUT ANY WARRANTY; without even the implied warranty of andrej@1808: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the andrej@1808: # GNU General Public License for more details. andrej@1808: # andrej@1808: # You should have received a copy of the GNU General Public License andrej@1808: # along with this program; if not, write to the Free Software andrej@1808: # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. andrej@1808: andrej@1826: andrej@1881: from __future__ import absolute_import andrej@1826: from __future__ import print_function andrej@1796: import os andrej@1796: import sys andrej@1796: import unittest andrej@1832: import time andrej@1832: andrej@2419: import six andrej@1809: import pytest andrej@1796: import wx andrej@1809: import ddt andrej@1796: andrej@1808: import conftest andrej@1808: import Beremiz andrej@1819: import PLCOpenEditor andrej@1796: andrej@1796: andrej@1796: class UserApplicationTest(unittest.TestCase): andrej@1796: def InstallExceptionHandler(self): edouard@1961: def handle_exception(e_type, e_value, e_traceback, exit=False): andrej@1796: # traceback.print_exception(e_type, e_value, e_traceback) andrej@1796: self.exc_info = [e_type, e_value, e_traceback] andrej@1796: self.exc_info = None andrej@1796: self.old_excepthook = sys.excepthook andrej@1796: sys.excepthook = handle_exception andrej@1796: andrej@1796: def StartApp(self): andrej@1796: self.app = None andrej@1796: andrej@1796: def FinishApp(self): andrej@1796: wx.CallAfter(self.app.frame.Close) andrej@1796: self.app.MainLoop() andrej@1796: self.app = None andrej@1796: andrej@1809: def setUp(self): andrej@1809: self.app = None andrej@1809: andrej@1796: def tearDown(self): andrej@1796: if self.app is not None and self.app.frame is not None: andrej@1796: self.FinishApp() andrej@1796: andrej@1796: def RunUIActions(self, actions): andrej@1796: for act in actions: andrej@1796: wx.CallAfter(*act) andrej@1796: self.ProcessEvents() andrej@1796: andrej@1796: def CheckForErrors(self): andrej@1796: if self.exc_info is not None: andrej@1796: # reraise catched previously exception andrej@2419: exc_type = self.exc_info[0] andrej@2419: exc_value = self.exc_info[1] andrej@2419: exc_traceback = self.exc_info[2] andrej@2419: six.reraise(exc_type, exc_value, exc_traceback) andrej@1796: andrej@1796: def ProcessEvents(self): andrej@1847: for dummy in range(0, 30): andrej@1796: self.CheckForErrors() andrej@1796: wx.Yield() andrej@1796: time.sleep(0.01) andrej@1796: andrej@1796: andrej@1809: @ddt.ddt andrej@1796: class BeremizApplicationTest(UserApplicationTest): andrej@1796: """Test Beremiz as whole application""" andrej@1816: andrej@1796: def StartApp(self): andrej@1796: self.app = Beremiz.BeremizIDELauncher() andrej@1796: # disable default exception handler in Beremiz andrej@1796: self.app.InstallExceptionHandler = lambda: None andrej@1796: self.InstallExceptionHandler() edouard@1961: self.app.handle_exception = sys.excepthook andrej@1796: self.app.PreStart() edouard@1961: self.ProcessEvents() andrej@1818: self.app.frame.Show() andrej@1818: self.ProcessEvents() andrej@1818: self.app.frame.ShowFullScreen(True) andrej@1818: self.ProcessEvents() andrej@1796: andrej@1796: def FinishApp(self): andrej@1796: wx.CallAfter(self.app.frame.Close) andrej@1796: self.app.MainLoop() andrej@1796: time.sleep(1) andrej@1796: self.app = None andrej@1796: andrej@1816: def GetSkippedProjectTreeItems(self): andrej@1816: """ andrej@1816: Returns the list of skipped items in the project tree. andrej@1816: andrej@1816: Beremiz test don't need to skip any elemnts in the project tree. andrej@1816: """ andrej@1816: return [] andrej@1816: andrej@1796: def OpenAllProjectElements(self): andrej@1808: """Open editor for every object in the project tree""" andrej@1796: self.app.frame.ProjectTree.ExpandAll() andrej@1796: self.ProcessEvents() andrej@1796: item = self.app.frame.ProjectTree.GetRootItem() andrej@1819: skip = self.GetSkippedProjectTreeItems() andrej@1819: tree_id = self.app.frame.ProjectTree.GetId() andrej@1796: while item is not None: andrej@1796: self.app.frame.ProjectTree.SelectItem(item, True) andrej@1796: self.ProcessEvents() andrej@1819: if item not in skip: andrej@1819: event = wx.lib.agw.customtreectrl.TreeEvent( andrej@1819: wx.lib.agw.customtreectrl.wxEVT_TREE_ITEM_ACTIVATED, andrej@1819: tree_id, item) andrej@1819: self.app.frame.OnProjectTreeItemActivated(event) andrej@1796: self.ProcessEvents() andrej@1796: item = self.app.frame.ProjectTree.GetNextVisible(item) andrej@1796: andrej@1816: def CheckTestProject(self, project): andrej@1796: sys.argv = ["", project] andrej@1796: self.StartApp() andrej@1796: self.OpenAllProjectElements() andrej@1816: user_actions = self.GetUserActions() andrej@1816: self.RunUIActions(user_actions) andrej@1816: self.FinishApp() andrej@1796: andrej@1816: def GetProjectPath(self, project): andrej@1816: return os.path.abspath(os.path.join(os.path.dirname(__file__), "..", project)) andrej@1816: andrej@1816: def GetUserActions(self): andrej@1816: """ andrej@1816: Returns list of user actions that will be executed andrej@1816: on every test project by testCheckProject test. andrej@1816: """ andrej@1796: user_actions = [ andrej@1796: [self.app.frame.SwitchFullScrMode, None], andrej@1796: [self.app.frame.SwitchFullScrMode, None], andrej@1796: [self.app.frame.CTR._Clean], andrej@1796: [self.app.frame.CTR._Build], andrej@1796: [self.app.frame.CTR._Connect], andrej@1796: [self.app.frame.CTR._Transfer], andrej@1796: [self.app.frame.CTR._Run], andrej@1796: [self.app.frame.CTR._Stop], andrej@1796: [self.app.frame.CTR._Disconnect], andrej@1822: [self.app.frame.CTR._Clean], andrej@1796: ] andrej@1816: return user_actions andrej@1796: andrej@1796: def testStartUp(self): andrej@1796: """Checks whether the app starts and finishes correctly""" andrej@1817: sys.argv = [""] andrej@1796: self.StartApp() andrej@1796: self.FinishApp() andrej@1796: andrej@1809: @ddt.data( andrej@1809: "first_steps", andrej@1809: "logging", andrej@1809: "traffic_lights", andrej@1809: "wxGlade", andrej@1809: "python", andrej@1809: "wiimote", andrej@1809: "wxHMI", andrej@1809: ) andrej@1809: @pytest.mark.timeout(30) andrej@1809: def testCheckProject(self, name): andrej@1816: """ andrej@1816: Checks that test PLC project can be open, andrej@1816: compiled and run on SoftPLC. andrej@1816: """ andrej@1816: project = self.GetProjectPath(name) andrej@1826: print("Testing example " + name) andrej@1816: self.CheckTestProject(project) andrej@1796: andrej@1796: andrej@1819: class PLCOpenEditorApplicationTest(BeremizApplicationTest): andrej@1819: """Test PLCOpenEditor as whole application""" andrej@1819: andrej@1819: def StartApp(self): andrej@1819: self.app = PLCOpenEditor.PLCOpenEditorApp() andrej@1819: # disable default exception handler in application andrej@1819: self.app.InstallExceptionHandler = lambda: None andrej@1819: self.InstallExceptionHandler() andrej@1819: self.app.Show() andrej@1819: self.ProcessEvents() andrej@1819: self.app.frame.ShowFullScreen(True) andrej@1819: self.ProcessEvents() andrej@1819: andrej@1819: def FinishApp(self): andrej@1819: wx.CallAfter(self.app.frame.Close) andrej@1819: self.app.MainLoop() andrej@1819: time.sleep(1) andrej@1819: self.app = None andrej@1819: andrej@1819: def GetSkippedProjectTreeItems(self): andrej@1819: """ andrej@1819: Returns the list of skipped items in the project tree. andrej@1819: andrej@1819: Root item opens dialog window for project settings. andrej@1819: To avoid code that handles closing dialog windows just skip this item. andrej@1819: """ andrej@1819: return [self.app.frame.ProjectTree.GetRootItem()] andrej@1819: andrej@1819: def GetUserActions(self): andrej@1819: return [] andrej@1819: andrej@1819: def GetProjectPath(self, project): andrej@1819: """Open PLC program in every Beremiz test project""" andrej@1819: project_dir = BeremizApplicationTest.GetProjectPath(self, project) andrej@1819: return os.path.join(project_dir, "plc.xml") andrej@1819: andrej@1819: andrej@1796: if __name__ == '__main__': andrej@1850: conftest.init_environment() andrej@1796: unittest.main()