NI TestStand

cancel
Showing results for 
Search instead for 
Did you mean: 

C# UI for Parallel Testing Different Tests

I am trying to develop a customized User Interface for a product testing application using Teststand 3.5. There are a few things I have issues with:
 
1. Selecting a sequence file through a path, so that it is fixed and that the application will only run the two test sequences selected for the two execution view managers and sequence view managers. The examples only show how to do this by using a windows style file browser.
 
2. Fixing the sequence in each selected file to run, ie the main sequence.
 
3. Associating the Application Manager display file event and execution event with the corresponding sequence and execution manager controls.
 
I have looked at the CSharp examples and they do not indicate how to do this. I found another example that opens up multiple windows as child based on the number of executions, which is also not what I am trying to achieve.
 
The application I am developing is to run two different sequence files, displaying data in a split pane. If someone has an example of a parallel process or autoscheduled process model file that enables running two different tests, it would be of so much help.
 
Any info or suggestion from you pros would be much appreciated.
 
Thanks,
 
Heather
0 Kudos
Message 1 of 6
(5,284 Views)
Heather,

Could you please clarify some details of what you are trying to accomplish.  Do you have two different SequenceFiles that you want to display, or is it simply a matter of displaying two different Sequences from the same SequenceFile?  Are you using a Parallel Process Model to execute a single Sequence File?

For every SequenceView control there must be a separate SequenceViewManager.  Similarly, each SequenceView that is used as an ExecutionView must have a separate ExecutionViewManager.  If you are trying to display two different Sequences and two different Executions, then you will need two SequenceViewManager controls and two ExecutionViewManager controls.

(a)  If you do not want the user to be able to select certain sequences, than you should remove the Sequence List combo box and its controlling logic.  You can set the displayed sequence for a specific SequenceView by using the SequenceFileViewManager control.

To set what SequenceFile is displayed by the SequenceFileViewManager use:

axSequenceFileViewMgr.SequenceFile = SequenceFileObj;

To set what Sequence is displayed you can use:

axSequenceFileViewMgr.Sequence = SequenceFileObj.GetSequenceByName("MainSequence");

(b)  If you do not want the user to be able to select SequenceFiles, you should remove the SequenceFile list combo box and its controlling logic.  To manually load a file, use the ApplicationMgr control:

axApplicationMgr.OpenSequenceFile("mySequenceFile.seq");

(c)  The most difficult part is to set the ExecutionViewMgr controls to handle separate Execution objects.  You should use the ApplicationMgr.DisplayExecution event callback to handle which Executions are displayed.  The DisplayExecution event passed in an object that contains the Execution object that is to be displayed.  For the Paralell or Batch Process Model each test socket is handled by a different Execution object.  You must implement some logic here to determine which Execution object should be assigned to a specific ExecutionViewMgr.

To assign an Execution object to an ExecutionViewMgr use:

axExecutionViewMgr.Execution = e.exec;  // where e.exec is the Execution object is passed into the DisplayExecution callback function

If you can provide a little bit more detail on what you are trying to accomplish, I would be happy to provide my input.

Thanks,

Tyler T.


0 Kudos
Message 2 of 6
(5,263 Views)

Hello Tyler,

Thank you so much for your response and most helpful suggestions.

Attached in a word document is a screen shot of the GUI.

As you can see there are two panes for testing. Right now I have the open file button and combo boxes just so I could be able to open up sequence files. Then plan is to remove them and have the tests show up as programmatically set.

There are two SequenceViewMgrs and ExecutionViewMgrs as you pointed, and one ApplicationMgr.

Further on your suggestion my specific dilemma is:

1. ApplicationMgr.OpenSequenceFile("mySequenceFile.seq");

The above will allow opening only one sequence file and I actually have to open two separate sequence files, totally independant of each other, with locks to allow for resource sharing, to test two different products. How could I achieve this? Also, the sequence file or its steps are not really meant to be displayed (yet) and the sequenceviews that you can see on the GUI will actually only display the execution.

2. I am actually not sure how to assign the callback such that the execution event is capable of associating the ExecutionViewMgr control. I have tried to implement, by overriding, the DisplayExecution event handler, but it doesnt do what I want by using e.exec, because I have not made the association of or initialized such that e.exec corresponds to a particular ExecutionViewMgr. Question is, where would this association be made? Would I also have to override the generate event so that I can customize the e.exec property to hold the particular ExecutionViewMgr name?

Currently I have not set up a process model such that it will run two separate files in parallel, but once I can get the GUI to display results as desired, that would indeed be the next step.

Once again, thanks for your input.

0 Kudos
Message 3 of 6
(5,244 Views)
Heather,

1.  In regards to your question about opening two unrelated SequenceFiles:

In this case I suggest creating a top level Sequence.  The Sequence should be composed of two Sequence Calls each with a Precondition on the step.  Each Sequence Call will call your two separate Sequence Files.  With this structure you can make use of the standard Process Models such as the Batch Model or Paralell Process Model, which would be much easier than creating one from scratch.  With these models in mind, you can assume that the top level Sequence will be called twice.  However, you want each execution to only call one of the SubSequences.  With the Precondition you can check RunState.TestSockets.MyIndex, which refers to the execution index.  So Precondition on Sequence Call 1 would have a Precondition "RunState.TestSockets.MyIndex == 0".  For Sequence Call 2 you would use "RunState.TestSockets.MyIndex == 1".

This will also allow you to use the ApplicationMgr.OpenSequenceFile("") to load only one SequenceFile.  You can still hide the top level Sequence File from the Operator by setting the SequenceFileViewMgr to only display the Sequences that you want to see.

2.  Associating an Execution with an ExecutionViewMgr:

As I mentioned before, the association of an Execution with ExecutionViewMgr occurs in the DisplayExecution callback.  Take a look at the Full Featured C# OI found in the <TestStand>\OperatorInterfaces\NI\Full Featured\CSharp directory.  Assuming you are using the Paralell or Batch Process Model, you can again access the RunState.TestSockets.MyIndex parameters to determine which Execution should be associated with a certain ExecutionViewMgr.  The e.exec object that is sent into the DisplayExecution event can be used to determine which execution is being represented.  You can get the RunState by accessing the Thread property of the Execution which holds the SequenceContext.  It would look like this:

            // access the SequenceContext of the current Execution
            int frameId;
            NationalInstruments.TestStand.Interop.API.SequenceContext seqContext =
                e.exec.GetThread(0).GetSequenceContext(0, out frameId);

            // convert PropertyObject
            NationalInstruments.TestStand.Interop.API.PropertyObject seqContextPO =
                seqContext.AsPropertyObject();

            // lookup MyIndex
            int testSocket = System.Convert.ToInt32(seqContextPO.GetValNumber("RunState.TestSockets.MyIndex", 0));

            // assign e.exec to the right ExecutionViewMgr
            if (testSocket == 0)
            {    axExecutionViewMgr1.Execution = e.exec;    }
            else
            {    axExecutionViewMgr2.Execution = e.exec;    }

I'm currently working on an example that will perform this functionality.  I will post it as soon as it is available.

Thanks,

Tyler T.

0 Kudos
Message 4 of 6
(5,218 Views)
Thank you for your suggestion Tyler.
 
The idea to branch off two separate executions of separate sequence files, through one main file, based on a test socket precondition is brilliant. I have managed to get that to work without much difficulty in Test Stand.
 
However, when trying to follow the remainder of your suggestion, to display the execution in the C# UI, I do face difficulty. Basically, on every entry into the Display Execution Call back, the testsocket returned is = 0. I have followed the exact procedure you described earlier to extract the RunState.TestSockets.MyIndex property of the Sequence Context Property Object.
 
//access sequence context of current execution
int frameID=0;

NationalInstruments.TestStand.Interop.API.SequenceContext seqContext = e.exec.GetThread(0).GetSequenceContext(0, out frameID);

//convert property object

NationalInstruments.TestStand.Interop.API.PropertyObject seqContextPO = seqContext.AsPropertyObject();

//look up my index

int testSocket = System.Convert.ToInt32(seqContextPO.GetValNumber("RunState.TestSockets.MyIndex",0));

The above is as you described, but testSocket value always shows up as 0. I have set the station options and model options to run parallel testing of two sockets. As I mentioned, it works fine in Test Stand.

Any one seen this before?

Also, I was wondering if this occurs because basically there is one execution of the Main sequence, which then calls the other two sequences (seen as test steps. Even launching this in a new thread makes no difference). By the time the two separate sequence file precondition is reached, we have already established the e.exec to relate to a given execution view manager control.

0 Kudos
Message 5 of 6
(5,147 Views)
Heather,

I apologize, but I did not test the code I posted.  When I tried it on my end I ran into the same issue.  I did some investigating and as you suspected, the SequenceContext that is returned is not as I expected.  Instead it was only returning the SequenceContext of the top level Sequence, with the first Execution (Socket 0).  I started to play around with some code, and I did get a method that works properly.  In this method, instead of capturing the DisplayExecution event, I use UIMessageEvents.  UIMessageEvents are a way to communicate between the TestStand sequence and the OperatorInterface.  The ApplicationMgr is able to capture UIMessageEvents that are posted from the Sequences.  In order to post a UI Message Event, place an ActiveX Action step into a sequence with the following parameters:

Object:  RunState.Thread
Server:  TestStand API
Class:  Thread
Call Method:  PostUIMessageEx

eventCode
:  UIMsg_UserMessageBase
numericDataParam:  0 for SequenceFile 1 and 1 for SequenceFile 2
stringDataParam:  ""
activeXDataParam:  Nothing
synchronous:  True

You will want to add the ActiveX step to the beginning of both Sequences that are called from the main Sequence.  Set numericDataParam accordingly for each TestSocket.

The ApplicationMgr.UIMessageEvent is sent an event object that will contain each of these parameters.  We can use these parameters to determine which SequenceFile should be displayed.  After adding this event to the C# code, you should add the following code:

private void axApplicationMgr1_UIMessageEvent(object sender, NationalInstruments.TestStand.Interop.UI.Ax._ApplicationMgrEvents_UIMessageEventEvent e)
{
      if (e.uiMsg.Event == NationalInstruments.TestStand.Interop.API.UIMessageCodes.UIMsg_UserMessageBase)
      {
          if (e.uiMsg.NumericData == 0)
          {    axExecutionViewMgr1.Execution = e.uiMsg.Execution;    }
          else
          {    axExecutionViewMgr2.Execution = e.uiMsg.Execution;    }
      }
}

The first if statement checks what UIMessageEvent is being sent.  You can send multiple events as well as standard TestStand events.  All events 10,000 or above are for user events.  UIMsg_UserMessageBase is equivalent to 10,000.

Once we have determined that the correct UIMessage has been sent, then we simply need to check the NumericData property to determine which Execution should be assigned where.  Notice that Execution is a property of the uiMsg object.

This is a manner that will work.  The drawback is of course that you must insert this call into all the Sequences that you want to display, which does not make it as robust.  I will further investigate my other method, which may work for multiple cases.

Regards,

Tyler T.
0 Kudos
Message 6 of 6
(5,116 Views)