tests/ide_tests/load_and_build_tests.pytest/test_application.py
author Edouard Tisserant <edouard.tisserant@gmail.com>
Thu, 20 Jul 2023 16:24:12 +0200
changeset 3825 269987dd4fb0
parent 3750 f62625418bff
permissions -rw-r--r--
SVGHMI Py3 related fix in test project.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# This file is part of Beremiz, a Integrated Development Environment for
# programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
#
# Copyright (C) 2017: Andrey Skvortsov
#
# See COPYING file for copyrights details.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.




import os
import sys
import unittest
import time

import six
import pytest
import wx
import ddt

import conftest
import Beremiz
# import PLCOpenEditor


class UserApplicationTest(unittest.TestCase):
    def InstallExceptionHandler(self):
        def handle_exception(e_type, e_value, e_traceback, exit=False):
            # traceback.print_exception(e_type, e_value, e_traceback)
            self.exc_info = [e_type, e_value, e_traceback]
        self.exc_info = None
        self.old_excepthook = sys.excepthook
        sys.excepthook = handle_exception

    def StartApp(self):
        self.app = None

    def FinishApp(self):
        wx.CallAfter(self.app.frame.Close)
        self.app.MainLoop()
        self.app = None

    def setUp(self):
        self.app = None

    def tearDown(self):
        if self.app is not None and self.app.frame is not None:
            self.FinishApp()

    def RunUIActions(self, actions):
        for act in actions:
            wx.CallAfter(*act)
            self.ProcessEvents()

    def CheckForErrors(self):
        if self.exc_info is not None:
            # reraise catched previously exception
            exc_type = self.exc_info[0]
            exc_value = self.exc_info[1]
            exc_traceback = self.exc_info[2]
            six.reraise(exc_type, exc_value, exc_traceback)

    def ProcessEvents(self):
        for dummy in range(0, 30):
            self.CheckForErrors()
            wx.Yield()
            time.sleep(0.01)


@ddt.ddt
class BeremizApplicationTest(UserApplicationTest):
    """Test Beremiz as whole application"""

    def StartApp(self):
        self.app = Beremiz.BeremizIDELauncher()
        # disable default exception handler in Beremiz
        self.app.InstallExceptionHandler = lambda: None
        self.InstallExceptionHandler()
        self.app.handle_exception = sys.excepthook
        self.app.PreStart()
        self.ProcessEvents()
        self.app.frame.Show()
        self.ProcessEvents()
        self.app.frame.ShowFullScreen(True)
        self.ProcessEvents()

    def FinishApp(self):
        wx.CallAfter(self.app.frame.Close)
        self.app.MainLoop()
        time.sleep(1)
        self.app = None

    def GetSkippedProjectTreeItems(self):
        """
        Returns the list of skipped items in the project tree.

        Beremiz test don't need to skip any elemnts in the project tree.
        """
        return []

    def OpenAllProjectElements(self):
        """Open editor for every object in the project tree"""
        self.app.frame.ProjectTree.ExpandAll()
        self.ProcessEvents()
        item = self.app.frame.ProjectTree.GetRootItem()
        skip = self.GetSkippedProjectTreeItems()
        tree_id = self.app.frame.ProjectTree.GetId()
        while item is not None:
            self.app.frame.ProjectTree.SelectItem(item, True)
            self.ProcessEvents()
            if item not in skip:
                event = wx.lib.agw.customtreectrl.TreeEvent(
                    wx.lib.agw.customtreectrl.wxEVT_TREE_ITEM_ACTIVATED,
                    tree_id, item)
                self.app.frame.OnProjectTreeItemActivated(event)
            self.ProcessEvents()
            item = self.app.frame.ProjectTree.GetNextVisible(item)

    def CheckTestProject(self, project):
        sys.argv = ["", project]
        self.StartApp()
        self.OpenAllProjectElements()
        user_actions = self.GetUserActions()
        self.RunUIActions(user_actions)
        self.FinishApp()

    def GetProjectPath(self, project):
        return os.path.abspath(os.path.join(os.path.dirname(__file__), "..","..","projects", project))

    def GetUserActions(self):
        """
        Returns list of user actions that will be executed
        on every test project by testCheckProject test.
        """
        user_actions = [
            [self.app.frame.SwitchFullScrMode, None],
            [self.app.frame.SwitchFullScrMode, None],
            [self.app.frame.CTR._Clean],
            [self.app.frame.CTR._Build],
            [self.app.frame.CTR._Connect],
            [self.app.frame.CTR._Transfer],
            [self.app.frame.CTR._Run],
            [self.app.frame.CTR._Stop],
            [self.app.frame.CTR._Disconnect],
            [self.app.frame.CTR._Clean],
        ]
        return user_actions

    def testStartUp(self):
        """Checks whether the app starts and finishes correctly"""
        sys.argv = [""]
        self.StartApp()
        self.FinishApp()

    # TODO: also use "exemples/*" projects
    @ddt.data(
        #"first_steps",
        "logging",
        #"traffic_lights",
        #"wxGlade",
        #"python",
        #"wiimote",
        # "wxHMI",
    )
    @pytest.mark.timeout(300)
    def testCheckProject(self, name):
        """
        Checks that test PLC project can be open,
        compiled and run on SoftPLC.
        """
        project = self.GetProjectPath(name)
        print("Testing example " + name)
        self.CheckTestProject(project)


# class PLCOpenEditorApplicationTest(BeremizApplicationTest):
#     """Test PLCOpenEditor as whole application"""
# 
#     def StartApp(self):
#         self.app = PLCOpenEditor.PLCOpenEditorApp()
#         # disable default exception handler in application
#         self.app.InstallExceptionHandler = lambda: None
#         self.InstallExceptionHandler()
#         self.app.Show()
#         self.ProcessEvents()
#         self.app.frame.ShowFullScreen(True)
#         self.ProcessEvents()
# 
#     def FinishApp(self):
#         wx.CallAfter(self.app.frame.Close)
#         self.app.MainLoop()
#         time.sleep(1)
#         self.app = None
# 
#     def GetSkippedProjectTreeItems(self):
#         """
#         Returns the list of skipped items in the project tree.
# 
#         Root item opens dialog window for project settings.
#         To avoid code that handles closing dialog windows just skip this item.
#         """
#         return [self.app.frame.ProjectTree.GetRootItem()]
# 
#     def GetUserActions(self):
#         return []
# 
#     def GetProjectPath(self, project):
#         """Open PLC program in every Beremiz test project"""
#         project_dir = BeremizApplicationTest.GetProjectPath(self, project)
#         return os.path.join(project_dir, "plc.xml")
# 

if __name__ == '__main__':
    conftest.init_environment()
    unittest.main()