On 2 synchronously acting machines: How to terminate a unittest on failure and move to following unittests

Asked by Aravind

Hi,

I am running two scripts parallelly on two different machines(as two different user logins into a Desktop app).
My test suite contains three unittests say, test1, test2 and test3.

I'll make it much more clear.

Script1 on machine1->>

class Machine1Tests(unittest.TestCase,CommonMethods):
 def setUp(self):
    pass
 def test1(self):
    self.login()
    self.doSomething1()
    self.logout()
 def test2(self):
    self.login()
    self.doSomething2()
    self.logout()
 def test3(self):
    self.login()
    self.doSomething3()
    self.logout()

Script1 on machine2->>

class Machine2Tests(unittest.TestCase,CommonMethods):
 def setUp(self):
    pass
 def test1(self):
    self.login()
    self.doSomething1()
    self.logout()
 def test2(self):
    self.login()
    self.doSomething2()
    self.logout()
 def test3(self):
    self.login()
    self.doSomething3()
    self.logout()

Suppose on machine1, in my login method in test1, something goes wrong and my unittest fails, I'm using an assert False statement which will terminate the script and hence it moves on to other unittests following it, meanwhile on machine 2, still the test1 continues. But what I need is like, when test1 somehow fails on Machine1, Machine2 script should somehow terminate and parallely both machine should start test2 at the same time. I want to have this kind of sync between the two because in all the unittests, there is some interaction between two users on both machines.

I tried using an xml-rpc call like, if something fails on Machine 1, before I make an assert statement, I make an xml-rpc call to the other Machine 2 to terminate. But unfortunately I know only scripts to either terminate the entire script as such, but thats not what i want here. Calling tearDown method(which contains a taskill command also won't work because it kills the app only, not terminate the unittest)

So, my question is that, is there any other mechanism to terminate that particular unittest at the other end as well ?

Thanks in advance.

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
RaiMan
Solved:
Last query:
Last reply:
Revision history for this message
RaiMan (raimund-hocke) said :
#1

If you want a 2-way communication between the 2 machines, you need to start an XML-RPC server on both machines.

The handlers should be the unit tests (preferably 1 per class)

One machine should be the master in the sense, that it tells the other machine: now we start with test1.
in startup and teardown there should be the frame communication, that takes care, that in all cases test2 starts on both machines only after test1 has finished on both machines (you might use class variables).

If one machine fails in the test, it has to tell the other machine via XML-RPC call. In the tests you have to poll a class variable e.g. stopRunning at the points, where the concurrent running of the other machine is needed. If stopRunning was set to true by the other machine, you have to skip the rest of the test.

You might delegate the workload of the test to a thread, that can be simply terminated when needed (thread.exit() ), so you do not need a series of "if not stopRunning" or "while not stopRunning".

Revision history for this message
Aravind (a4aravind) said :
#2

Thanks Raiman, but I didn't quite get the idea of using thread here. Can you please give an idea on how we can use threads here. I'm not that familiar with Python threads :(

Revision history for this message
Best RaiMan (raimund-hocke) said :
#3

if you want to skip something depending on a switch, you have to possibilities:

--- version 1 (using if/while/ ...)

# some preps here
# including setting the global switch to true (means should run)
... some code independent of switch
if switch:
    # some code to be executed as long as switch is false
... some code independent of switch
if switch:
    # some code to be executed as long as switch is false
... and more of these

If the switch is set to false from somewhere else, the respective code snippets will be skipped

--- version 2 (using a simple thread)
def workload():
    # here goes all the stuff that should be run as test
    # ...
    # telling main we terminated successfully
    global running
    running = false
    return # this ends the thread

switch = true
running = true
sub = thread.start_new_thread(workload, )
# we wait until either running or switch is set to false
while switch and running:
    wait(1)
if running:
    sub.exit() # terminate the thread if it is still running

... more info http://docs.python.org/2/library/thread.html

Revision history for this message
Aravind (a4aravind) said :
#4

Hi Raiman,

I couldn't successfully do it as there are already many other xml-rpc calls both ways between Machine1 and Machine2 methods. So it'll become more complex for me if I add this also.

May I ask you about another option something like this:
test1 in Machine1 fails-> It sends an xml-rpc call to Machine2 where it calls an "assert False" statement.
But the problem is that, again Machine 2 won't be affected anyway since the "assert False" is again going to affect Machine 1 since the xml-rpc call has to return something back to the place from where it has been called.

So my question narrows down like, Is there anyother way to give an assert False statement which terminates the particular unittest in Machine2 by an xml-rpc call from Machine1.

Thanks.

Revision history for this message
RaiMan (raimund-hocke) said :
#5

The challenge in this case is the need to implement some global state handling:

somehow simplified:
state = running: both machines should proceed
state = shouldStop: one machine has reached a point, where the other machine should stop running the current test case.
state = stopped: both machines are idle and might start the next test case
state = shouldRun: one machine has started a test and the other should start it too

both machines have to constantly check this global state and react accordingly.
The implementation is much easier, if one machine acts as master and hence controls the state handler according to shouldRun.

There is no way to "inject" an assert false, if there are no preps for that in the above sense.

... and the smoothest implementation is the version 2 above, where the testcases are run as threads in the state handlers on both machines, which communicate independently from the workload.

Revision history for this message
Aravind (a4aravind) said :
#6

Thanks RaiMan, that solved my question.