2016-06-11 22 views
4

我有一個返回這樣的值夾具:pytest - >如何測試方法使用固定裝置的返回值類下

import pytest 

@pytest.yield_fixture(scope="module") 
def oneTimeSetUp(browser): 
    print("Running one time setUp") 
    if browser == 'firefox': 
     driver = webdriver.Firefox() 
     print("Running tests on FF") 
    else: 
     driver = webdriver.Chrome() 
     print("Running tests on chrome") 
    yield driver 
    print("Running one time tearDown") 

此夾具從另一個夾具被讀取命令獲取瀏覽器的價值線路選項。

然後我有一個測試類,我有多個測試方法,他們都想使用相同的返回值驅動程序來進行測試。

import pytest 

@pytest.mark.usefixtures("oneTimeSetUp") 
class TestClassDemo(): 

    def test_methodA(self): 
     # I would like to use the driver value here 
     # How could I do this? 
     # Something like this 
     self.driver.get("https://www.google.com") 
     self.driver.find_element(By.ID, "some id") 
     print("Running method A") 

    def test_methodB(self): 
     print("Running method B") 

使用self.driver失敗,出現錯誤消息

self = <test_class_demo.TestClassDemo object at 0x102fb6c18> 

    def test_methodA(self): 
>  self.driver.get("https://www.google.com") 
E   AttributeError: 'TestClassDemo' object has no attribute 'driver' 

我知道我可以通過夾具作爲參數的地方,我想使用的每一個方法,但不是最好的方法,因爲我需要在每種方法中都這樣,它應該可以傳遞給類,然後在所有測試方法中使用它。

什麼是我可以使驅動程序對象可用於方法的最佳方式?

EDIT 1:

創建夾具在conftest.py這樣的建議

@pytest.yield_fixture(scope="class") # <-- note class scope 
def oneTimeSetUp(request, browser): # <-- note the additional `request` param 
    print("Running one time setUp") 
    if browser == 'firefox': 
     driver = webdriver.Firefox() 
     driver.maximize_window() 
     driver.implicitly_wait(3) 
     print("Running tests on FF") 
    else: 
     driver = webdriver.Chrome() 
     print("Running tests on chrome") 

    ## add `driver` attribute to the class under test --> 
    if request.cls is not None: 
     request.cls.driver = driver 
    ## <-- 

    yield driver 
    print("Running one time tearDown") 

我還有一個類,哪個對象需要在TestClassDemo和我需要通過相同的驅動程序實例。認爲這是類ABC

class ABC(): 

    def __init(self, driver): 
     self.driver = driver 

    def enterName(self): 
     # Do something with driver instance 

然後在TestClassDemo

@pytest.mark.usefixtures("oneTimeSetUp", "setUp") 
class TestClassDemo(unittest.TestCase): 

    # I need to create an object of class ABC, so that I can use it here 
    # abc = ABC(self.driver) 

    @pytest.fixture(scope="class", autouse=True) 
    def setup(self): 
     self.abc = ABC(self.driver) 
    # I tried this, but it's not working 
    # This error message shows up 
    # AttributeError: 'TestClassDemo' object has no attribute 'driver' 

    def setup_module(self): 
    self.abc = ABC(self.driver) 
    # This also does not work 
    # Error message -> AttributeError: 'TestClassDemo' object has no attribute 'abc' 


    def test_methodA(self): 
     self.driver.get("https://google.com") 
     self.abc.enterName("test") 
     print("Running method A") 

    def test_methodB(self): 
     self.abc.enterName("test") 
     print("Running method B") 

這ABC對象應該是在其他TEST_方法也可使用。

所有這些類是獨立的模塊,我的意思是在單獨的.py文件說。

另請在回答中解釋什麼是最好的方式來使用,而不是產量驅動程序實例。

編輯2:

在這個例子中沒有產量,這將是也運行oneTimeTearDown的最佳方式?我跑的刪除步驟的收率

@pytest.fixture(scope="class") 
def oneTimeSetUp(request, browser): 
    print("Running one time setUp") 
    if browser == 'firefox': 
     driver = webdriver.Firefox() 
     driver.maximize_window() 
     driver.implicitly_wait(3) 
     print("Running tests on FF") 
    else: 
     driver = webdriver.Chrome() 
     print("Running tests on chrome") 

    if request.cls is not None: 
     request.cls.driver = driver 

而且我使用單元測試類試過之後,但是當我使用高清setUpClass(CLS),我是不是能夠使用在TEST_方法實例化的對象。所以我不知道如何實現這一點。

我也想提供命令行參數,像在命令行中的瀏覽器,當我試圖單元測試,我不得不寫在每一類中的命令行參數。我只想在一個地方提供它們,就像測試套件一樣。在這裏最明智的幫助我。

我對計算器的一個問題,但沒有得到迴應。你能看看這個嗎? Python unittest passing arguments to parent test class

感謝

感謝

回答

2

有使用是在py.text unittest integration documentation概括了一種技術,可以對您有所幫助...內置request夾具。否則,我不知道如何在不提供指定燈具作爲方法參數的情況下訪問燈具的返回值。現在

@pytest.yield_fixture(scope="class") # <-- note class scope 
def oneTimeSetUp(request, browser): # <-- note the additional `request` param 
    print("Running one time setUp") 
    if browser == 'firefox': 
     driver = webdriver.Firefox() 
     print("Running tests on FF") 
    else: 
     driver = webdriver.Chrome() 
     print("Running tests on chrome") 

    ## add `driver` attribute to the class under test --> 
    if request.cls is not None: 
     request.cls.driver = driver 
    ## <-- 

    yield driver 
    print("Running one time tearDown") 

您可以訪問driver作爲一個階級屬性,TestClassDemo,因爲你在你的例子有(即self.driver應該工作)。

需要注意的是,您的燈具必須使用scope='class',否則request對象將不具備cls屬性。

我希望有幫助!


UPDATE

I have one more class, which object in need in the TestClassDemo and I need to pass the same driver instance to the class. Consider it as class ABC

這是很難知道沒有更多的情況下,但在我看來,或許您可以在同一時間實例化一個ABC對象脫身,你實例化driver ...在oneTimeSetUp夾具中。例如...

@pytest.yield_fixture(scope="class") 
def oneTimeSetUp(request, browser): 
    print("Running one time setUp") 
    if browser == 'firefox': 
     driver = webdriver.Firefox() 
     driver.maximize_window() 
     driver.implicitly_wait(3) 
     print("Running tests on FF") 
    else: 
     driver = webdriver.Chrome() 
     print("Running tests on chrome") 

    if request.cls is not None: 
     request.cls.driver = driver 
     request.cls.abc = ABC(driver) # <-- here 

    yield driver 
    print("Running one time tearDown") 

但是如果你只需要一個測試類或兩個ABC例如,以下是如何使用一個固定的類定義...

@pytest.mark.usefixtures("oneTimeSetUp", "setUp") 
class TestClassDemo(unittest.TestCase): 
    @pytest.fixture(autouse=True) 
    def build_abc(self, oneTimeSetUp): # <-- note the oneTimeSetup reference here 
     self.abc = ABC(self.driver) 

    def test_methodA(self): 
     self.driver.get("https://google.com") 
     self.abc.enterName("test") 
     print("Running method A") 

    def test_methodB(self): 
     self.abc.enterName("test") 
     print("Running method B") 

我不會對第二個例子特別滿意。第三個選項是使另一個與oneTimeSetUp完全分開的yield_fixture或類似的,並返回一個ABC實例,並且驅動程序已經打包。

哪種方式最適合你?不確定。您需要根據您的工作情況來決定。

後人注意到pytest夾具只是糖和一點魔力是適當的。如果你覺得困難,你根本不需要使用它們。 pytest很高興執行vanilla unittest TestCases。


Also please explain in the answer what is the best way to use instead of yield driver instance.

這是我腦子裏想的......

@pytest.fixture(scope="class") 
def oneTimeSetUp(request, browser): 
    print("Running one time setUp") 
    if browser == 'firefox': 
     driver = webdriver.Firefox() 
     driver.maximize_window() 
     driver.implicitly_wait(3) 
     print("Running tests on FF") 
    else: 
     driver = webdriver.Chrome() 
     print("Running tests on chrome") 

    if request.cls is not None: 
     request.cls.driver = driver 

...請注意,這不返回(或產量)的驅動程序對象,這意味着它不再將這個燈具作爲一個命名參數提供給一個函數/方法是有用的,如果所有的測試用例都被寫爲類(由你的例子建議),這應該沒問題。

但是,如果要將燈具作爲命名參數使用,請不要這樣做。

+0

非常感謝解決方案,我有幾個後續問題。 你能編輯你的答案來解釋最後一行嗎? 「如果您不打算在其他測試功能中使用oneTimeSetUp夾具(例如通過命名參數),那麼上述代碼當然可以進一步簡化。」 一個重要的問題: 如果我想在我的TestClassDemo中初始化另一個類的對象,那麼我應該在哪裏初始化它?我還需要將驅動程序傳遞給另一個類的對象。請幫助,你的回答非常棒。我真的很努力地完成這個工作很多天 –

+0

TestClassDemo中應該有__init __()來創建另一個類的對象嗎?是否可以從__init __()提供驅動程序給該對象,還是隻能在測試方法中使用它? –

+0

Hi @SunShine,我剛剛刪除了最後一句,因爲它構造得不好,也沒有什麼幫助。爲了澄清,我的意思是,如果使用'request'夾具爲你工作,**每**測試,那麼你不需要使用yield_fixture或返回/產生一個值。 – Marty

相關問題