简体   繁体   English

导入和使用模块时单元测试属性错误

[英]Unit test Attribute error when importing a module and using it

The following is my directory for automation which contains three files, I am trying to run the unittest file test_page.py by importing Base.py. 以下是我的自动化目录,其中包含三个文件,我试图通过导入Base.py运行unittest文件test_page.py。 Base.py contains browser setup and tear down, it accepts user arguments ( browser, username and password) and logs in to the site. Base.py包含浏览器设置和拆卸,它接受用户参数(浏览器,用户名和密码)并登录到该站点。 But when I run the test_page.py I get some errors. 但是当我运行test_page.py时,出现一些错误。 The problem is I need to get the browser instance from Base.py which I am unable to. 问题是我需要从Base.py获取浏览器实例,但我无法这样做。 I tried assigning the Browser().browser to a variable but that opens a new instance. 我尝试将Browser()。browser分配给变量,但这会打开一个新实例。 I need to use the same instance of browser that Base.py is using. 我需要使用与Base.py使用的浏览器相同的实例。

    Automation
       __init__.py
         Base.py
         test_page.py

Base.py Base.py

        import sys
        import argparse
        from selenium import webdriver
        import datetime

        parser = argparse.ArgumentParser()
        parser.add_argument('browser', default='chrome', help='Types of browser:chrome, firefox, ie')
        parser.add_argument('username', help='This is the  username')
        parser.add_argument('password', help='This is the  password')
        args = parser.parse_args()

        setup_parameters = sys.argv[1:]


        class Browser(object):

            url = 'https:someurl'
            start_time = datetime.datetime.today()


            def __init__(self):
                self.username = setup_parameters[1]
                self.password = setup_parameters[2]
                if setup_parameters[0] == 'chrome':
                    self.browser = webdriver.Chrome('C:\Python37\chromedriver.exe')
                    print("Running tests on Chrome browser on %s" % self.start_time)


                elif setup_parameters[0] == 'ie':
                    self.browser = webdriver.Ie()
                    print("Running tests on Internet Explorer browser on %s" % self.start_time)


                elif setup_parameters[0] == 'firefox':
                    self.browser = webdriver.Firefox()
                    print("Running tests on Firefox browser on %s" % self.start_time)


                elif setup_parameters[0] == 'None':
                    print('No browser type specified.... continuing with the default browser')
                    self.browser = webdriver.Chrome()

            def login(self):
                # Method used to log in to the site
                self.browser.get(self.url)
                self.browser.implicitly_wait(10)
                self.browser.maximize_window()
                self.browser.find_element_by_id("Username").send_keys(self.username)
                self.browser.find_element_by_id("Password").send_keys(self.password)
                self.browser.find_element_by_id("btnLogin").click()

            def close(self):
                # Closing the browser window and terminating the test
                self.browser.close()
                print("Test(s) ended on {} at {}".format(setup_parameters[0], datetime.datetime.today()))


        if __name__ == '__main__':
            Browser().login()
            Browser().close()

test_page.py test_page.py

    from unittest import TestSuite
    from unittest import TestCase
    from selenium import webdriver
    import time
    import sys
    import Base
    from Base import Browser

    class TestHomePage(unittest.TestCase):

        def setUp(self):
            self.driver = Browser().browser
            self.login = Browser().login()

        def test_links(self):
            self.driver.find_elements_by_link_text('click this link').click()

        def tearDown(self):
            self.close = Browser().close()


    if __name__ == '__main__':
        unittest.main()

    When I run test_page.py, I get the following error

    C:\Users\Projects\PortalAutomation>python test_page.py chrome username password

    EEE
    ======================================================================
    ERROR: chrome (unittest.loader._FailedTest)
    ----------------------------------------------------------------------
    AttributeError: module '__main__' has no attribute 'chrome'

    ======================================================================
    ERROR: 1EADMIN (unittest.loader._FailedTest)
    ----------------------------------------------------------------------
    AttributeError: module '__main__' has no attribute 'username'

    ======================================================================
    ERROR: password1 (unittest.loader._FailedTest)
    ----------------------------------------------------------------------
    AttributeError: module '__main__' has no attribute 'password'

    ----------------------------------------------------------------------
    Ran 3 tests in 0.000s

    FAILED (errors=3)

You're calling argparse in your Base.py file. 您正在Base.py文件中调用argparse Don't do that. 不要那样做 Move these lines to another file, or wrap them in if __name__ == __main__ : 将这些行移动到另一个文件,或者if __name__ == __main__它们包装起来:

if __name__ == __main__
    parser = argparse.ArgumentParser()
    parser.add_argument('browser', default='chrome', help='Types of browser:chrome, firefox, ie')
    parser.add_argument('username', help='This is the  username')
    parser.add_argument('password', help='This is the  password')
    args = parser.parse_args()

If you don't put these lines in another file or inside of if __name__ == "__main__" , that section of code will be run upon import , not when calling test_page.py from the command line. 如果您不将这些行放在另一个文件中,也不放在if __name__ == "__main__"内部, if __name__ == "__main__"该部分代码将在import上运行,而不是从命令行调用test_page.py时运行。

You also don't want to be using argparse in conjunction with unittest . 您也不想将argparseunittest结合使用。 Test Base.py using unittest , and setup the arguments you might need for the class in setUp . 使用unittest测试Base.py ,并在setUp设置类所需的参数。 I recommend you pass in username and password into the constructor of your Browser object so you can easily write a test that uses a canned username/pw. 我建议您将usernamepassword传递到Browser对象的构造函数中,以便您可以轻松编写使用罐头用户名/密码的测试。 You can do that like so: 您可以这样做:

class Browser(object):

    url = 'https:someurl'
    start_time = datetime.datetime.today()

    def __init__(self, driver, username, password):
        self.driver = driver
        self.username = username
        self.password = password
        if self.driver == 'chrome':
        ...

then you can write a test like this: 那么您可以编写如下测试:

def setUp(self):
    browser_obj = Browser('chrome', 'some_username', 'some_password')
    self.driver = browser_obj.browser
    self.login = browser_obj.login()

def test_links(self):
    self.driver.find_elements_by_link_text('click this link').click()

def tearDown(self):
    browser_obj.close()

and then invoke your unit test with a simple python test_page.py (no arguments necessary). 然后使用简单的python test_page.py调用您的单元测试(无需任何参数)。

When you run in prod, you can call Base.py with arguments, like Base.py chrome username password . 在prod中运行时,可以使用诸如Base.py chrome username password参数调用Base.py Usually people don't test their argparse logic too thoroughly if at all: as it's not exactly quantum physics to pass in arguments to existing classes/function. 通常,人们根本不会对argparse逻辑进行彻底的测试:因为将参数传递给现有的类/函数并不是完全是量子物理学。

Note that your original test is making several browser objects instead of using the same one. 请注意,您最初的测试是制作多个浏览器对象,而不是使用相同的对象。 You probably don't want this. 您可能不想要这个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM