Home > Net >  Cannot run multiple instance of JPYPE (JVM) when running Selenium tests in Python
Cannot run multiple instance of JPYPE (JVM) when running Selenium tests in Python

Time:07-12

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.

  • Related