0

i would like to know why this code opens mozilla twice, and why it doesn´t close it when finishes. Furthermore, i don´t understand 100% why login is a class with a function, and not a function directly.

> import unittest
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class LoginDetails(object): 
    def __init__ (self):
        self.driver = webdriver.Firefox()

    def logindetails(self, username, password):
        driver = self.driver
        driver.maximize_window()
        driver.get("https://miclaro.claro.com.ar/")

        driver.implicitly_wait(30)

        driver.find_element_by_id("_58_login_movil").send_keys(username)

        driver.find_element_by_id("_58_password_movil").send_keys(password)

        driver.find_element_by_id("btn-home-login").click()


        # Login Success

class TestLogin(unittest.TestCase):

    def setUp(self):
        self.ld = LoginDetails()
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(30)

    def test_sr_Login(self):
        self.ld.logindetails("user", "pass")

    def tearDown(self):
        self.driver.close()

if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()

Thank you very much!

2 Answers 2

3

This is because you instantiate webdriver twice - once inside the TestCase and once inside the LoginDetails class.

Why the other answer is not entirely correct

The WebDriver should not be controlled by the LoginDetails class in this case. LoginDetails class is very close to a Page Object notation representation and, hence, should be given the driver "from outside". Plus, opening browser in one class and closing it in the other is making the code close to "Spaghetti".

Better solution

Control the webdriver from the TestCase class and "share" with the LoginDetails:

import unittest
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class LoginDetails(object): 
    def __init__ (self, driver):
        self.driver = driver

    def logindetails(self, username, password):
        driver = self.driver
        driver.maximize_window()
        driver.get("https://miclaro.claro.com.ar/")

        driver.implicitly_wait(30)

        driver.find_element_by_id("_58_login_movil").send_keys(username)

        driver.find_element_by_id("_58_password_movil").send_keys(password)

        driver.find_element_by_id("btn-home-login").click()


class TestLogin(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(30)
        self.ld = LoginDetails(self.driver)

    def test_sr_Login(self):
        self.ld.logindetails("user", "pass")

    def tearDown(self):
        self.driver.close()
Sign up to request clarification or add additional context in comments.

Comments

2

Firefox opens twice

In your test self.ld = LoginDetails() runs the __init__ function of LoginDetails() which in turn runs webdriver.Firefox() then you issue the same in the next line in the test case. That is why Firefox opens twice.

Firefox does not close

For the same reason as above Firefox is not closed. The tearDown of your test case only closes the instance of webdriver.Firefox() defined in the test case itself not the one opened via the __init__ function of the class.

Why LoginDetails is a class

LoginDetails is a class in this case to keep webdriver.Firefox() persistent throughout your code. If it would be a function you would open one Firefox session each time you run the function. Unless you specify webdriver.Firefox() outside the function and then pass it to the function.

Corrected Code

The following code uses the class functionality:

import unittest
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class LoginDetails(object): 
    def __init__ (self):
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(30)

    def logindetails(self, username, password):
        self.driver.maximize_window()
        self.driver.get("https://miclaro.claro.com.ar/")

        self.driver.implicitly_wait(30)

        self.driver.find_element_by_id("_58_login_movil").send_keys(username)

        self.driver.find_element_by_id("_58_password_movil").send_keys(password)

        self.driver.find_element_by_id("btn-home-login").click()

    def __del__(self):
        ''' ADDED based on comment by alecxe '''
        self.driver.close()

class TestLogin(unittest.TestCase):

    def setUp(self):
        self.ld = LoginDetails()

    def test_sr_Login(self):
        self.ld.logindetails("user", "pass")

    def tearDown(self):
        # driver is closed by LoginDetails
        pass

if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()

5 Comments

I think driver should not be controlled by the LoginDetails class. LoginDetails is very close to a Page Object notation representation and, hence, should be given the driver "from outside". Plus, opening browser in one class and closing it in the other is making it close to "spaghetti".
In my view that depends on what you want to do with the class. In your solution you don't need a class. Login Details could be as well a function. I tried to answer the question why LoginDetails is a class. You are right though, that one should not open and close the connection at different places in the code. I hope you don't mind that I include that comment in my answer.
Has LoginDetails a special meaning in relation to selenium? Otherwise from what I can see in the code sample it is a new object without inheritance. You are right though if you want to resemble a Page Object you should give the driver "from outside".
Thanks for the feedback and changes. I like that we have 2 different solutions here for the OP to choose from.
Thank you very much people, it has been very useful for me, specially because i could understand how it works entirely. Thanks for sharing your knowledge with me, you are awesome.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.