I want to execute a python script in between of testCase but it is giving me error saying from PIL import Image ModuleNotFoundError: No module named ‘PIL’ katalon
if I run the same python script through terminal it works
please help with this as this is a blocker for us
In a Katalon Studio project, I wrote a file named <projectDir>/helloworld.py
, with content like this:
#!/usr/bin/env python
print("Hello World")
I created a Katalon Test Case named “Test Cases/runPy”, with the following codes:
import java.lang.Runtime
import java.lang.Process
import java.lang.String
import java.lang.System
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.IOException
String command = "/Users/kazurayam/.pyenv/shims/python ./helloworld.py"
try {
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
When I ran the Test Case, in the Console I saw the following messages:
2023-02-27 21:49:54.077 DEBUG testcase.runPy - 1: command = "/Users/kazuakiurayama/.pyenv/shims/python ./helloworld.py"
2023-02-27 21:49:54.085 DEBUG testcase.runPy - 2: try
2023-02-27 21:49:54.087 DEBUG testcase.runPy - 1: process = getRuntime().exec(command)
2023-02-27 21:49:54.120 DEBUG testcase.runPy - 2: reader = new java.io.BufferedReader(new java.io.InputStreamReader(process.getInputStream()))
2023-02-27 21:49:54.179 DEBUG testcase.runPy - 3: line = <not implemented yet for class: org.codehaus.groovy.ast.expr.EmptyExpression>
2023-02-27 21:49:54.183 DEBUG testcase.runPy - 4: while (line = reader.readLine() != null)
2023-02-27 21:49:54.324 DEBUG testcase.runPy - 1: out.println(line)
Hello World
2023-02-27 21:49:54.347 DEBUG testcase.runPy - 5: reader.close()
2023-02-27 21:49:54.367 INFO c.k.katalon.core.main.TestCaseExecutor - END Test Cases/runPy
As you see, my Katalon Test Case ran a Python script successfully.
your example is not running python.
your example is calling system functions, which calls a certain shell, which call python to execute the code.
altough it may look it was a solution, is not.
is just an workaround.
@titan.a typed some characters in a Terminal window, which calls a certain shell, which call python to execute the code.
Because it looks the same, "Runtime.getRuntime().exec(command);"
invoked by could be a solution for @titan.a.
@bionel, what’s the difference of a solution and a workaround for you?
A black terminal screen or a white GUI window, if it can catch problems, either is good enough for me.
Well, yeah, and that’s why your solution may work, since exec()
does, mostly, the same.
But it is somehow dependant on the shell. If the script don’t crash or throw errors, will be ok’ish
A better approach will be to use ProcessBuilder, to have a fine grain controll overr STDOUT and STDERR.
An example (and some other approaches) can be found here:
Yes, ProcessBuilder is better.
The following code uses ProcessBuilder, which works just the same as above.
import java.lang.Runtime
import java.lang.Process
import java.lang.ProcessBuilder
import java.lang.String
import java.lang.System
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.IOException
import java.util.stream.Collectors
String executable = "/Users/kazurayam/.pyenv/shims/python"
String pyscript = "./helloworld.py"
try {
ProcessBuilder processBuilder = new ProcessBuilder(executable, pyscript)
processBuilder.redirectErrorStream(true)
Process process = processBuilder.start();
List<String> results = readProcessOutput(process.getInputStream())
assert results != null, "Results should not be empty"
int exitCode = process.waitFor()
assert exitCode == 0, "exit code was expected to be 0 but was ${exitCode}"
results.forEach({ line ->
println(line)
})
} catch (IOException e) {
e.printStackTrace();
}
private List<String> readProcessOutput(InputStream inputStream) throws IOException {
BufferedReader output = new BufferedReader(new InputStreamReader(inputStream))
return output.lines().collect(Collectors.toList());
}
This is dependant on the shell as well; no different from Runtime.
But it redirects STDERR to STDOUT.
Previous example does not.
I created a new Python script: “helloError.py” as
import sys
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
eprint("Hello Error")
I created another Test Case:
import java.lang.Runtime
import java.lang.Process
import java.lang.ProcessBuilder
import java.lang.String
import java.lang.System
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.IOException
import java.util.stream.Collectors
String executable = "/Users/kazurayam/.pyenv/shims/python"
String pyscript = "./helloError.py"
try {
ProcessBuilder processBuilder = new ProcessBuilder(executable, pyscript)
//processBuilder.redirectErrorStream(true)
Process process = processBuilder.start();
List<String> results = readProcessOutput(process.getInputStream())
assert results != null, "Results should not be empty"
List<String> errors = readProcessOutput(process.getErrorStream())
int exitCode = process.waitFor()
println "exitCode=${exitCode}"
results.forEach({ line ->
println(line)
})
if (errors != null && errors.size() > 0) {
println "STDERR:"
errors.forEach({ line ->
println(line)
})
}
} catch (IOException e) {
e.printStackTrace();
}
private List<String> readProcessOutput(InputStream inputStream) throws IOException {
BufferedReader output = new BufferedReader(new InputStreamReader(inputStream))
return output.lines().collect(Collectors.toList());
}
When I ran this, I saw in the Console
2023-02-28 18:35:11.698 INFO c.k.katalon.core.main.TestCaseExecutor - --------------------
2023-02-28 18:35:11.701 INFO c.k.katalon.core.main.TestCaseExecutor - START Test Cases/runPy3
2023-02-28 18:35:12.289 DEBUG testcase.runPy3 - 1: executable = "/Users/kazuakiurayama/.pyenv/shims/python"
2023-02-28 18:35:12.290 DEBUG testcase.runPy3 - 2: pyscript = "./helloError.py"
2023-02-28 18:35:12.293 DEBUG testcase.runPy3 - 3: try
2023-02-28 18:35:12.295 DEBUG testcase.runPy3 - 1: processBuilder = new java.lang.ProcessBuilder(executable, pyscript)
2023-02-28 18:35:12.304 DEBUG testcase.runPy3 - 2: process = processBuilder.start()
2023-02-28 18:35:12.319 DEBUG testcase.runPy3 - 3: results = readProcessOutput(process.getInputStream())
2023-02-28 18:35:12.339 DEBUG testcase.runPy3 - 1: output = new java.io.BufferedReader(new java.io.InputStreamReader(inputStream))
2023-02-28 18:35:12.365 DEBUG testcase.runPy3 - 2: return output.lines().collect(java.util.stream.Collectors.toList())
2023-02-28 18:35:12.498 DEBUG testcase.runPy3 - 4: assert results != null : "Results should not be empty"
2023-02-28 18:35:12.503 DEBUG testcase.runPy3 - 5: errors = readProcessOutput(process.getErrorStream())
2023-02-28 18:35:12.509 DEBUG testcase.runPy3 - 1: output = new java.io.BufferedReader(new java.io.InputStreamReader(inputStream))
2023-02-28 18:35:12.514 DEBUG testcase.runPy3 - 2: return output.lines().collect(java.util.stream.Collectors.toList())
2023-02-28 18:35:12.518 DEBUG testcase.runPy3 - 6: exitCode = process.waitFor()
2023-02-28 18:35:12.520 DEBUG testcase.runPy3 - 7: println(exitCode=$exitCode)
exitCode=0
2023-02-28 18:35:12.570 DEBUG testcase.runPy3 - 8: results.forEach({ java.lang.Object line -> ... })
2023-02-28 18:35:12.580 DEBUG testcase.runPy3 - 9: if (errors != null && errors.size() > 0)
2023-02-28 18:35:12.585 DEBUG testcase.runPy3 - 1: println("STDERR:")
STDERR:
2023-02-28 18:35:12.587 DEBUG testcase.runPy3 - 2: errors.forEach({ java.lang.Object line -> ... })
Hello Error
2023-02-28 18:35:12.624 INFO c.k.katalon.core.main.TestCaseExecutor - END Test Cases/runPy3
Katalon’s Test Case could run Python scripts successfully.
Not only Python, Katalon’s Test Case would be able to run Node.js, Ruby, PowerShell, Perl, AWK as well by the above approach. Command line shell is the best capable glue.