简体   繁体   中英

CANoe: How to select and start test cases from XML Test Module from Python using CANoe COM interface?


currently I am able to:

  • start CANoe application
  • load a CANoe configuration file
  • load a test setup file

    def load_test_setup(self, canoe_test_setup_file: str = None) -> None: logger.info( f'Loading CANoe test setup file <{canoe_test_setup_file}>.') if self.measurement.Running: logger.info( f'Simulation is currently running, so new test setup could \\ not be loaded!') return self.test_setup.TestEnvironments.Add(canoe_test_setup_file) test_environment = self.test_setup.TestEnvironments.Item(1) logger.info(f'Loaded test environment is <{test_environment.Name}>.')


How can I access the XML Test Module loaded with the test setup (tse) file and select tests to be executed?

The last before line in your snippet is most probably causing the issue. I have been trying to fix this issue for quite some time now and finally found the solution.

Somehow when you execute the line self.test_setup.TestEnvironments.Item(1)

win32com creates an object of type TestSetupItem which doesn't have the necessary properties or methods to access the test cases. Instead we want to access objects of collection types TestSetupFolders or TestModules . win32com creates object of TestSetupItem type even though I have a single XML Test Module (called AutomationTestSeq) in the Test Environment as you can see here .

There are three possible solutions that I found.


  1. Manually clearing the generated cache before each run.

Using win32com.client.DispatchWithEvents or win32com.client.gencache.EnsureDispatch generates a bunch of python files that describe CANoe's object model.

If you had used either of those before, TestEnvironments.Item(1) will always return TestSetupItem instead of the more appropriate type objects.

To remove the cache you need to delete the C:\\Users\\{username}\\AppData\\Local\\Temp\\gen_py\\{python version} folder.

Doing this every time is of course not very practical.


  1. Force win32com to always use dynamic dispatch. You can do this by using:

canoe = win32com.client.dynamic.Dispatch("CANoe.Application") Any objects you create using canoe from now on, will be dynamically dispatched.

Forcing dynamic dispatch is easier than manually clearing the cache folder every time. This gave me good results always. But doing this will not let you have any insight into the objects. You won't be able to see the acceptable properties and methods for the objects.


  1. Typecast TestSetupItem to TestSetupFolders or TestModules .

This has the risk that if you typecast incorrectly, you will get unexpected results. But has worked well for me so far. In short: win32.CastTo(test_env, "ITestEnvironment2") . This will ensure that you are using the recommended object hierarchy as per CANoe technical reference.

Note that you will also have to typecast TestSequenceItem to TestCase to be able to access test case verdict and enable/disable test cases.

Below is a decent example script.

"""Execute XML Test Cases without a pass verdict"""
import sys
from time import sleep
import win32com.client as win32

CANoe = win32.DispatchWithEvents("CANoe.Application")
CANoe.Open("canoe.cfg")

test_env = CANoe.Configuration.TestSetup.TestEnvironments.Item('Test Environment')

# Cast required since test_env is originally of type <ITestEnvironment>
test_env = win32.CastTo(test_env, "ITestEnvironment2")
# Get the XML TestModule (type <TSTestModule>) in the test setup
test_module = test_env.TestModules.Item('AutomationTestSeq')

# {.Sequence} property returns a collection of <TestCases> or <TestGroup>
# or <TestSequenceItem> which is more generic
seq = test_module.Sequence
for i in range(1, seq.Count+1):
    # Cast from <ITestSequenceItem> to <ITestCase> to access {.Verdict}
    # and the {.Enabled} property
    tc = win32.CastTo(seq.Item(i), "ITestCase")
    if tc.Verdict != 1: # Verdict 1 is pass
        tc.Enabled = True
        print(f"Enabling Test Case {tc.Ident} with verdict {tc.Verdict}")
    else:
        tc.Enabled = False
        print(f"Disabling Test Case {tc.Ident} since it has already passed")


CANoe.Measurement.Start()
sleep(5)   # Sleep because measurement start is not instantaneous
test_module.Start()
sleep(1)

Just continue what you have done.

The TestEnvironment contains the TestModules. Each TestModule contains a TestSequence which in turn contains the TestCases.

Keep in mind that you cannot individual TestCases but only the TestModule. But you can enable and disable individual TestCases before execution by using the COM-API.

( typing this from the top of my head, might not work 100% )

test_module = test_environment.TestModules.Item(1) # of 2 or whatever
test_sequence = test_module.Sequence
for i in range(1, test_sequence.Count + 1):
    test_case = test_sequence.Item(i)
    if ...:
        test_case.Enabled = False # or True

test_module.Start()

You have to keep in mind that a TestSequence can also contain other TestSequences (ie a TestGroup). This depends on how your TestModule is setup. If so, you have to take care of that in your loop and descend into these TestGroups while searching for your TestCase of interest.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM