2017-10-08 1 views
0

Ich habe Probleme beim Komponententest in Python. Ich habe ein Objekt, retailer, das ein anderes Objekt erstellt, deal. deal bezieht sich auf ein Attribut in retailer erstellt, so dass ich übergeben Sie eine Referenz:So erstellen Sie ein Objekt aus einem anderen Objekt im Python-Komponententest

class deal(): 
    def __init__(self, deal_container, parent): 

Das deal_container Attribut kommt auch von retailer, die ihre eigenen Methoden aufruft, es zu schaffen. Also, wie erstelle ich alles, was ich brauche, um ein deal Objekt zu erstellen?

Muss ich in meinem Komponententest eine Instanz von retailer erstellen und dann die Methode in dem Objekt aufrufen, das deal erstellt?

Kann ich FactoryBoy verwenden, um eine Instanz von retailer zu erstellen, und wie schließe ich die Methode ein, die deal in diesem Objekt erstellt?

Was ist der beste Weg, um dies zu nähern?

Hier ist der Komponententest. Ich gründe die soup_obj ich viel geben müssen bis:

class TestExtractString(TestCase): 
    fixtures = ['deals_test_data.json'] 

    def setUp(self): 
     with open('/home/danny/PycharmProjects/askarby/deals/tests/BestBuyTest.html', 'r') as myfile: 
      text = myfile.read().replace('\n', '') 
     self.soup_obj = bs4.BeautifulSoup(text,"html.parser") 
     self.deal = self.soup_obj.find_all('div',attrs={'class':'list-item'})[0] 

    def test_extracts_title(self): 
     z = Retailer.objects.get(pk=1) 
     s = dealscan.retailer(z) 
     d = dealscan.deal(self.deal,s) 
     result = d.extract_string(self.deal,'title') 

und hier ist das entsprechende Bit der deal Klasse in dealscan. Es gibt eine retailer Klasse, die eine deal erstellt, aber ich habe nicht einmal das Bit in retailer geschrieben, das deal noch erstellt. Ich hoffe, dass ich die Bits, die ich für deal brauche, verspotten kann, ohne auf retailer überhaupt zurückgreifen zu müssen, aber wie gehe ich dann mit der Tatsache um, dass deal Referenzen retailer?

class deal(): 
    def __init__(self, deal_container, parent): 
     ''' 
     Initializes deal object 
     Precondition: 0 > price 
     Precondition: 0 > old_price 
     Precondition: len(currency) = 3 

     :param deal_container: obj 
     ''' 
     self.css = self.parent.css 

     self.deal_container = deal_container 
     self.parent = parent 
     self.title = self.extract_string('title') 
     self.currency = self.parent.currency 
     self.price = self.extract_price('price') 
     self.old_price = self.extract_price('old_price') 
     self.brand = self.extract_string('brand') 
     self.image = self.extract_image('image') 
     self.description = self.extract_string('description') 

     #define amazon category as clearance_url 
     #define all marketplace deals 

    def __str__(self): 
     return self.title 

    def extract_string(self, element, deal): 
     ''' 

     :param object deal: deal object to extract title from 
     :param string element: element to look for in CSS 
     :return string result: result of string extract from CSS 
     ''' 
     tag = self.css[element]['tag'] 
     attr = self.css[element]['attr'] 
     name = self.css[element]['name'] 
     result = deal.find(tag, attrs={attr: name}) 
     if result: 
      if element == 'title': 
       return result.text 
      elif element == 'price': 
       result = self.extract_price(result).text 
       if result: 
        return result 
      elif element == 'image': 
       result = self.extract_image(result) 

     return False 
+1

Es spielt keine Rolle, wie diese Objekte erstellt werden. Der Komponententest sollte sich darauf konzentrieren, was ein Deal ist, wie sein Verhalten ist. So können Sie weitergeben, was Sie wollen: echte Objekte, "mock" Objekte oder Stubs, solange der Test bestimmen kann, ob sich Deal korrekt verhält. – quamrana

+0

Bitte zeigen Sie uns den Code des Codes der "Einheit", die Sie testen möchten, und erklären Sie das Ziel des Tests. –

+0

Das stimmt. Aber um zu testen, was Deal tut, muss ich einen Deal erstellen, und er benötigt einen Elternteil, weil er auf ein Attribut verweist, das der Elternteil hat. Wenn ich versuche, ein Geschäft außerhalb des übergeordneten Objekts zu erstellen, bekomme ich: AttributeError: 'Deal' Objekt hat kein Attribut 'Eltern'. Ich muss 'Deal' erstellen, damit es diesen Fehler nicht wirft. Was bedeutet, dass ich ein Elternobjekt erstellen muss. – RubyNoob

Antwort

0

Das Problem ist, dass das Objekt Deal auf das übergeordnete Element verweist, bevor es das Attribut self.parent setzt. Verwenden Sie:

self.parent = parent   
self.css = self.parent.css 
self.deal_container = deal_container 

und die AttributeError geht weg.

Wie bei der Frage, ob es gut ist, ein Objekt zu verwenden, um ein anderes Objekt in einem Komponententest zu erstellen, ist die Antwort, dass Sie Mocks verwenden können, aber es ist in Ordnung. Die Verwendung einer Hilfsmethode zum Einrichten des übergeordneten Objekts in setUp ist akzeptabel und erleichtert das Lesen des Codes und kann die Testleistung ein wenig verbessern.

Verwandte Themen