I am currently developing an automation testing framework using Selenium and Python. The project needs to use an Oracle database and because of that I decided to use JayDeBeApi in conjunction with JPype. However, upon executing multiple test cases I am facing the “OS error: JVM cannot be restarted” error triggered by the setUpClass
line: “jpype.startJVM()”.
I have done some research and found that only one JVM instance through the whole python program execution can be run. I thought that placing the jpype.startJVM() and jpype.shutdownJVM() under the setUpClass and tearDownClass methods would suffice as they suppose to be executed only 1 time through the whole test executing. However, I found it had no effect.
Project goes like this, first the parent testing class where I initiate the JVM
class ParentTest(unittest.TestCase):
@classmethod
def setUpClass(self):
jpype.startJVM(jpype.getDefaultJVMPath(), Constant.ojdbcpath)
print('› Test starting and JVM turned on')
@classmethod
def tearDownClass(self):
jpype.shutdownJVM()
print('> Test finished and JVM closed')
Then the usual unittest cases:
class Example_Test (ParentTest):
driver = None
def setUp(self):
self.driver = webdriver.Chrome(Constant.driver)
self.driver.set_window_size(Constant.screen_width, Constant.screen height)
def tearDown(self):
self.driver.close()
self.driver.quit()
def test example(self) :
print ('> Executing test case...')
Which perform some queries in the following way:
def get_status(_parameter):
with Database() as db:
query = "SELECT * FROM TABLE WHERE COLUMN = " str(_parameter)
results = db.query(query)
return str(results[0][0])
Being Database the class which connects to the Oracle DB:
class Database:
def __init__ (self):
self._connection = None
self._cursor = None
def __enter__ (self):
try:
self.connection = jaydebeapi.connect(Constant.dbdriver, Constant.ldap, [Constant.dbuser, Constant.dbpassword])
# print("› Connected to database!')
self._cursor = self._connection.cursor()
except Exception as err:
print (err)
return self
def __exit__ (self, exc_type, exc_val, exc_tb):
try:
self._cursor.close()
# print("› Closed cursor connection!")
self._connection.close()
# print("› Closed database connection! ')
except Exception as err:
print (err)
return self
def query (self, sql):
try:
self._cursor.execute (sql)
self.result = self._cursor.fetchall()
return self.result
except Exception as err:
print (err)
And finally all test cases are executed using a small suite and runner in the following format:
test1 = TestLoader().loadTestsFromtestCase(...)
test2 = TestLoader().loadTestsFromtestCase(...)
suite = TestSuite([test1, test2])
h = HTMLTestRunner(output=FOLDER).run(suite)
Do you know if there is a different approach to initialize the JVM only one time? I am a bit lost in this as I really expected that setUpClass
would solve everything. Please also let me know any suggestions you have.
CodePudding user response:
After some introspection I decided to place the JVM part inside the suite file which executes all the test cases.
So based in previous example
try:
jpype.startJVM(jpype.getDefaultJVMPath(), Constant.ojdbcpath)
test1 = TestLoader().loadTestsFromtestCase(...)
test2 = TestLoader().loadTestsFromtestCase(...)
suite = TestSuite([test1, test2])
h = HTMLTestRunner(output=FOLDER).run(suite)
finally:
jpype.shutdownJVM()
I was able to execute multiple test cases in that way and at the end of the execution the JVM was shutdown.