2011-03-02 75 views
3

我無法弄清楚如何在我的系統中設計類。將對象C從A級發送到B級

在classA中創建對象硒(它模擬用戶在網站上的操作)。

在這個ClassA中,我創建了另一個對象,如SearchScreen,Payment_Screen和Summary_Screen。

# -*- coding: utf-8 -*- 
from selenium import selenium 
import unittest, time, re 

class OurSiteTestCases(unittest.TestCase): 
    def setUp(self): 
     self.verificationErrors = [] 

     self.selenium = selenium("localhost", 5555, "*chrome", "http://www.someaddress.com/") 
     time.sleep(5) 
     self.selenium.start()   

    def test_buy_coffee(self): 

     sel = self.selenium 

     sel.open('/') 
     sel.window_maximize() 

     search_screen=SearchScreen(self.selenium) 
     search_screen.choose('lavazza') 

     payment_screen=PaymentScreen(self.selenium) 
     payment_screen.fill_test_data() 

     summary_screen=SummaryScreen(selenium) 
     summary_screen.accept() 


    def tearDown(self): 
     self.selenium.stop() 
     self.assertEqual([], self.verificationErrors) 

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

它例如SearchScreen模塊:

class SearchScreen: 
    def __init__(self,selenium): 
     self.selenium=selenium 

    def search(self): 
     self.selenium.click('css=button.search') 

我想知道是否有什麼好的那些類的設計?

+1

爲什麼你需要SearchScreen等類?通過將它們分成不同的課程,你獲得了什麼? – 2011-03-02 10:39:36

+0

我只給出了我的測試用例的僞代碼示例。我有很多測試用例,所以我創建了SearchScreen等,以便不復制代碼 – user278618 2011-03-02 10:55:27

+0

@ user278618:請在我的答案結尾處查看我的更新。 – aknuds1 2011-03-02 13:43:26

回答

3

你的方法很好。你有一套工具類,每個工具類都需要知道它的目標。然後你有一個工具包類來協調這些工具在一個特定的目標上。

class AgreePrice: 
    def __init__(self, connection): ... 

class PlaceOrder: 
    def __init__(self, connection): ... 

class ConfirmAvailability: 
    def __init__(self, connection): ... 

class BookingService: 
    def __init__(self, connection): ... 

    def book(self): 
     for Command in (ConfirmAvailability, AgreePrice, PlaceOrder): 
      command = Command(self.connection) 
      command.run() 
      assert command.success() 

有什麼都沒有錯這些類型的階級結構的是,事實上他們拿出所有的時間,並且是當個人「工具」類不能方便地在一個功能放在一個相當不錯的設計。

如果你發現自己有一個擁有數十種方法的類,其中很多可以根據特定的任務分組,那麼這是一個很好的重構。

作爲一般規則,您希望確保您的'工具'類(SearchScreen等)在概念上低於您的控制器(您的測試用例)。他們是給你的。

最簡單的這些工具類是Function Object設計模式的一種形式。雖然在你的情況下,你在每個對象上調用的不僅僅是一種方法,所以它們更復雜一些。


或者簡而言之。你的設計很好,而且很常見。

3

如果SearchScreen/PaymentScreen/SummaryScreen只執行測試邏輯,它看起來像我可能只是將該邏輯放在OurSiteTestCases的實用程序方法中。

的test_buy_coffee方法可能的設計(取決於你真正做SearchScreen等):

def test_buy_coffee(self): 

    sel = self.selenium 

    sel.open('/') 
    sel.window_maximize() 

    # Replace SearchScreen 
    self.__choose_search() 
    # Replace PaymentScreen 
    self.__fill_payment_data() 
    # Replace SummaryScreen 
    self.__accept_summary() 

編輯: 如果您需要分解出在__choose_search,__fill_payment_data和__accept_summary測試邏輯,在測試之間分享它,你可以在通用的模塊/軟件包中編寫相應的實用測試功能。或者,您可以編寫一個包含硒對象(self.selenium)的測試基類,並具有「受保護的」實用方法_choose_search,_fill_payment_data和_accept_summary。這一切都取決於你的情況是什麼實際:)

1

也許你可以使用責任鏈模式:

定義: 避免給多個對象有機會處理請求連接到其接收器請求的發送者。鏈接接收對象並沿着鏈傳遞請求,直到對象處理它爲止。

的例子是在C#中:

Handler h1 = new ConcreteHandler1(); 

    Handler h2 = new ConcreteHandler2(); 

    Handler h3 = new ConcreteHandler3(); 

    h1.SetSuccessor(h2); 

    h2.SetSuccessor(h3); 



    // Generate and process request 

    int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 }; 


    foreach (int request in requests) 
    { 
    h1.HandleRequest(request); 
    } 

這裏是你可以看到完整的文檔:http://www.dofactory.com/Patterns/PatternChain.aspx#_self1

相關問題