### Question:
JythonScriptEngine implements ScriptEngine { @Override public WorkerRunnable createWorkerRunnable() throws EngineException { final PyObject pyTestRunner; try { pyTestRunner = m_testRunnerFactory.__call__(); } catch (final PyException e) { throw new JythonScriptExecutionException( "creating per-thread TestRunner object", e); } if (!pyTestRunner.isCallable()) { throw new JythonScriptExecutionException( "The result of '" + TEST_RUNNER_CALLABLE_NAME + "()' is not callable"); } return new JythonWorkerRunnable(pyTestRunner); } JythonScriptEngine(final ScriptLocation script); @Override WorkerRunnable createWorkerRunnable(); @Override WorkerRunnable createWorkerRunnable(final Object testRunner); @Override void shutdown(); @Override String getDescription();  }### Answer:
@Test public void testWorkerRunnableNoCallable() throws Exception { createFile( m_script.getFile(), "class TestRunner:pass"); final JythonScriptEngine scriptEngine = new JythonScriptEngine(m_script); try { scriptEngine.createWorkerRunnable(); fail("Expected EngineException"); } catch (final EngineException e) { assertContains(e.getMessage(), "is not callable"); } }
@Test public void testWorkerRunnableBadRunner() throws Exception { createFile( m_script.getFile(), "class TestRunner:", " def __init__(self): raise Exception('a problem')" ); final JythonScriptEngine scriptEngine = new JythonScriptEngine(m_script); try { scriptEngine.createWorkerRunnable(); fail("Expected JythonScriptExecutionException"); } catch (final JythonScriptExecutionException e) { assertContains(e.getShortMessage(), "a problem"); } }
@Test public void testWorkerRunnableBadRunner2() throws Exception { createFile( m_script.getFile(), "class TestRunner:", " def __call__(self): raise Exception('a problem')"); final JythonScriptEngine scriptEngine = new JythonScriptEngine(m_script); final WorkerRunnable runnable = scriptEngine.createWorkerRunnable(); try { runnable.run(); fail("Expected JythonScriptExecutionException"); } catch (final JythonScriptExecutionException e) { assertContains(e.getShortMessage(), "a problem"); } }
@Test public void testNewWorkerRunnableWithTestRunner() throws Exception { createFile( m_script.getFile(), "class TestRunner: pass"); final JythonScriptEngine scriptEngine = new JythonScriptEngine(m_script); try { scriptEngine.createWorkerRunnable(null); fail("Expected JythonScriptExecutionException"); } catch (final JythonScriptExecutionException e) { assertContains(e.getMessage(), "is not callable"); } final Object badRunner = new Object(); try { scriptEngine.createWorkerRunnable(badRunner); fail("Expected JythonScriptExecutionException"); } catch (final JythonScriptExecutionException e) { assertContains(e.getMessage(), "is not callable"); } m_interpreter.exec("result=1"); m_interpreter.exec("def myRunner():\n global result\n result=99"); final PyObject goodRunner = m_interpreter.get("myRunner"); final WorkerRunnable workerRunnable = scriptEngine.createWorkerRunnable(goodRunner); assertEquals("1", m_interpreter.get("result").toString()); workerRunnable.run(); assertEquals("99", m_interpreter.get("result").toString()); final PyObject badRunner2 = m_interpreter.get("result"); try { scriptEngine.createWorkerRunnable(badRunner2); fail("Expected JythonScriptExecutionException"); } catch (final JythonScriptExecutionException e) { assertContains(e.getMessage(), "is not callable"); } }