### Question:
ExternalProcessRunner { public ProcessResult execute(String command, String... args) throws ProcessNotExecutableException, ProcessFailedException, InterruptedException { if (StringUtils.isEmpty(command)) { throw new IllegalArgumentException("command cannot be null"); } List<String> commandWithArgs = new ArrayList<>(); commandWithArgs.add(command); if (args != null && args.length > 0) { commandWithArgs.addAll(Arrays.asList(args)); } String commandWithArgsString = String.join(" ", commandWithArgs); log.info("Running an external command: " + commandWithArgsString); Process process; ProcessBuilder pb = new ProcessBuilder(commandWithArgs); pb.redirectErrorStream(true); try { process = pb.start(); } catch (IOException e) { log.error("Error starting external process: " + command, e); throw new ProcessNotExecutableException(e); } List<String> processOutput = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) { br.lines().forEach(processOutput::add); } catch (IOException e) { process.destroy(); IOUtils.closeQuietly(process.getErrorStream()); IOUtils.closeQuietly(process.getOutputStream()); log.error("External command not executable: " + commandWithArgsString, e); throw new ProcessNotExecutableException(e); } int exitCode; try { boolean hasExited = process.waitFor(TIMEOUT, TimeUnit.MILLISECONDS); if (!hasExited) { throw new ProcessFailedException("Process timed out"); } exitCode = process.exitValue(); log.info("External command finished with exit status {}", exitCode); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw e; } finally { process.destroy(); IOUtils.closeQuietly(process.getInputStream()); IOUtils.closeQuietly(process.getErrorStream()); IOUtils.closeQuietly(process.getOutputStream()); } ProcessResult processResult = new ProcessResult(commandWithArgsString, exitCode, processOutput); return processResult; }  ProcessResult execute(String command, String... args); ProcessResult executeAndThrowOnFailure(String command, String... args); static String processOutputToString(List<String> processOutput);  }### Answer:
@Test public void executeSuccess() { try { ExternalProcessRunner.ProcessResult processResult = externalProcessRunner.execute(MOCK_SUCCESS_SCRIPT, SCRIPT_ARGS); assertEquals(MOCK_SUCCESS_SCRIPT + " " + SCRIPT_ARGS, processResult.getCommandWithArgs()); assertEquals(0, processResult.getExitCode()); assertEquals("SUCCESS", processResult.getProcessOutput().get(0)); } catch (Exception e) { fail("should not throw exceptions"); } }
@Test public void executeScriptFail() throws Exception { ExternalProcessRunner.ProcessResult processResult = externalProcessRunner.execute(MOCK_FAIL_SCRIPT, SCRIPT_ARGS); assertEquals(MOCK_FAIL_SCRIPT + " " + SCRIPT_ARGS, processResult.getCommandWithArgs()); assertEquals(1, processResult.getExitCode()); assertEquals("FAIL", processResult.getProcessOutput().get(0)); }
@Test public void executeError() throws Exception { try { externalProcessRunner.execute(NON_EXISTING_SCRIPT, SCRIPT_ARGS); } catch (ProcessNotExecutableException e) { assertTrue(e.getCause() instanceof IOException); } }