2

I'm running Jenkins on a project written in Matlab. My build script is starting up Matlab with necessary arguments to run build script and exits.

As Matlab is an interpreted language, consecutive runs are dramatically faster so I'm trying to find a way to run Matlab and keep it open for future tests.

I also don't think this problem is related to Matlab only, Java is the same.

So the question is: Is there a way to keep process (Matlab in my case) open for future test runs?

Answers about a solution to Java or another interpreted language is welcome.

Sam Roberts
  • 23,951
  • 1
  • 40
  • 64
Ferit
  • 8,692
  • 8
  • 34
  • 59
  • 1
    This can be a complex problem in most cases, does [**this Q/A**](https://stackoverflow.com/questions/18781803/call-a-function-by-an-external-application-without-opening-a-new-instance-of-mat) help for the start? – Robert Seifert Jul 08 '17 at 15:53
  • @thewaywewalk Thanks. But I can't see how it can help :/ – Ferit Jul 08 '17 at 16:32
  • if none of the answer helps you, you should highly extend your question and explain why these answers don't work. Because I don't think there is a solution out of the box and everybody would just suggest the same as before. I also think, that the combination of jenkins and matlab is not very popular, so maybe you find help easier in a jenkins board. – Robert Seifert Jul 08 '17 at 20:41
  • @thewaywewalk Actually solution to Java would be %90 same with solution to Matlab. All I need is to find a logic to make Jenkins feed the same process with tests and collect results without exiting the process. – Ferit Jul 09 '17 at 03:10
  • 1
    @thewaywewalk By the way, after thinking for some time, that post inspired me. I'll share when I find a working solution. – Ferit Jul 09 '17 at 17:24
  • Adding the unit-testing tag to bring the question to the attention of @AndyCampbell , who might have some good advice. – Sam Roberts Jul 10 '17 at 08:57
  • @SamRoberts Thank you : ) – Ferit Jul 10 '17 at 09:12
  • Coming way late to the party here, but what kind of speedup are you seeing when MATLAB is warm? Do you have lots of very small projects? It would be interesting to see how much time the "warmth" of these MATLAB instances is saving you. The drawback of this approach is the increased complexity required and the fact that you don't get fresh sessions so there can be some undesirable effects on the environment that might be difficult to track down. Generally, I would prefer using a fresh fixture instead of a shared fixture unless the performance difference is significant. – Andy Campbell Aug 23 '17 at 20:06

1 Answers1

1

Disclaimer: I've never tried the following suggestion, and there might be difficulties I haven't considered. But I think it would probably work.

I think you should be able to use either the MATLAB Engine for Python (R2014b and above) or MATLAB Engine for Java (R2016b and above).

Instead of starting MATLAB each time you run a Jenkins job, start it once, with matlab -r 'matlab.engine.shareEngine'. This will run the MATLAB command matlab.engine.shareEngine at startup, making MATLAB available for connections from Python or Java.

Your Jenkins job could then run a small Python or Java script that would connect to the running MATLAB session, execute your testing code, clear up, and disconnect from MATLAB.

You'd need to make sure to pass back a result from MATLAB to Python/Java to indicate whether your tests had passed or failed, and then cause the Python/Java to exit with a status code reflecting that, so that Jenkins knows about the success/failure.

You'd also need to take care to clean up at the end of each run, as MATLAB would otherwise end up sharing state between test runs. And you'll also need to make sure that your test runs never crash MATLAB (or have some way of monitoring it and bringing it back up if it does crash).


Edit: Example as requested.

So (assuming you have a session of MATLAB running, that has been set up eith a shared as described above) you can connect to MATLAB from Python, and run your tests, using something like the following:

import matlab.engine
eng = matlab.engine.connect_matlab()
import StringIO
out = StringIO.StringIO()
err = StringIO.StringIO()
ret = eng.runmytests(nargout=1,stdout=out,stderr=err)
print(out.getvalue())
print(err.getvalue())
if ret:
    sys.exit(0)
else:
    sys.exit(1)

Notice the eng.runmytests. Here you are calling a MATLAB function runmytests. You would want to implement a MATLAB function runmytests.m that does something like the following:

function output = runmytests
import matlab.unittest.TestSuite;
try
    suite = TestSuite.fromPackage('testcases','IncludingSubpackages',true);
    results = run(suite);
    display(results);
catch e
    display(getReport(e,'extended'));
    output = false;
    return
end
output = ~any([results.Failed]);

The above example is not completely worked through; I'm afraid I don't have a Python environment on my machine right now to be able to test it out - you'll probably need to tweak it somewhat. But I hope it might be a decent starting point.

Sam Roberts
  • 23,951
  • 1
  • 40
  • 64
  • Thanks, sounds like a good idea! Could you give a little example about connecting to engine? – Ferit Jul 10 '17 at 09:14
  • Thank you very much, I think this approach will work. I'll share the results when I implement. – Ferit Jul 10 '17 at 10:18