2017-10-08 179 views
0

我无法理解Python中的单元测试。我有一个对象,retailer,它创建另一个对象dealdealretailer创建的属性,所以我传递一个参考:如何在Python单元测试中从另一个对象创建对象

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

deal_container属性也来自retailer,这就要求它自己的方法来创建它。那么如何创建我需要的所有东西来轻松制作一个deal对象?

是否必须在我的单元测试中创建一个retailer的实例,然后调用该对象中创建deal的方法?

我可以使用FactoryBoy创建retailer的实例,以及如何在该对象中包含创建deal的方法?

解决此问题的最佳方法是什么?

这里是单元测试。我设置了soup_obj我需要给交易:

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') 

和这里的deal类的相关位dealscan。有一个retailer类创建了一个deal,但我甚至没有在retailer中创建deal。我希望我可以模拟deal所需的位,而不必调用retailer,但那么我该如何处理deal引用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

这些对象的创建方式并不重要。单元测试应该关注'交易'的作用,它的行为。因此,只要测试可以确定交易行为是否正确,您就可以传入您喜欢的内容:真实对象,“模拟”对象或存根。 – quamrana

+0

请向我们展示您想要测试的“单位”的代码代码并解释测试的目标。 –

+0

没错。但为了测试什么交易,我必须创建一个交易,并且需要一个父项,因为它引用了父项的一个属性。因此,如果我尝试在其父对象之外创建交易,我会得到: AttributeError:'deal'对象没有属性'parent'。 我必须创建'交易',以便它不会抛出该错误。这意味着我需要创建一个父对象。 – RubyNoob

回答

0

问题是交易对象在设置self.parent属性之前引用了父对象。使用:

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

AttributeError消失。

至于在单元测试中是否使用对象来创建另一个对象是一个好问题,答案是可以使用mock,但这样做可以。使用帮助器方法在setUp中设置父对象一次是可以接受的,并且会使代码更易于阅读,并且可以稍微提高测试性能。