2015-01-05 3 views
0

У меня есть класс со следующим свойством clusters:UnitTest реализация Python свойство

import numpy as np 

class ClustererKmeans(object): 

    def __init__(self): 
     self.clustering = np.array([0, 0, 1, 1, 3, 3, 3, 4, 5, 5]) 

    @property 
    def clusters(self): 
     assert self.clustering is not None, 'A clustering shall be set before obtaining clusters' 
     return np.unique(self.clustering) 

Теперь я хочу, чтобы написать UnitTest для этого простого свойства. Я начинаю с:

from unittest import TestCase, main 
from unittest.mock import Mock 

class Test_clusters(TestCase): 

    def test_gw_01(self): 
     sut = Mock() 
     sut.clustering = np.array([0, 0, 1, 1, 3, 3, 3, 4, 5, 5]) 
     r = ClustererKmeans.clusters(sut) 
     e = np.array([0, 1, 3, 4, 5]) 
     # The following line checks to see if the two numpy arrays r and e are equal, 
     # and gives a detailed error message if they are not. 
     TestUtils.equal_np_matrix(self, r, e, 'clusters') 

if __name__ == "__main__": 
    main() 

Однако это не работает.

TypeError: 'property' object is not callable 

Далее я изменить строку r = ClustererKmeans.clusters(sut) на следующее:

r = sut.clusters 

Но опять же, я получаю неожиданное сообщение об ошибке.

AssertionError: False is not true : r shall be a <class 'numpy.ndarray'> (is now a <class 'unittest.mock.Mock'>) 

Есть ли простой способ проверить реализацию свойства в Python с использованием рамок unittest?

+2

Если вы не выполняете 'r = sut.clusters'? Аргумент 'self' отправляется по умолчанию. Я вижу, что другая проблема 'sut.clustering' не является правильным способом инициализации переменной класса. Вы должны отправлять его в качестве аргумента при инициализации класса – karthikr

+0

. Я попытался использовать 'r = sut.clusters', но в приведенном выше коде он возвращает объект Mock, а не массив numpy. – physicalattraction

ответ

1

К call property непосредственно в оригинальном кодекса ClustererKmeans.clusters(sut) может использоваться код ClustererKmeans.clusters.__get__(sut).

Даже если я фальшивый восторженный ИМХО, этот случай не является хорошим примером для его применения. Mocking полезны для удаления зависимостей от класса и ресурсов. В вашем случае ClustererKmeans имеют пустой конструктор, и для его разрыва нет никакой зависимости. Вы можете сделать это:

class Test_clusters(TestCase): 
    def test_gw_01(self): 
     sut = ClustererKmeans() 
     sut.clustering = np.array([0, 0, 1, 1, 3, 3, 3, 4, 5, 5]) 
     np.testing.assert_array_equal(np.array([0, 1, 2, 3, 4, 5]),sut.clusters) 

Если вы будете использовать насмешливый вы можете пропатчить ClustererKmeans() объект с помощью unittest.mock.patch.object:

def test_gw_01(self): 
    sut = ClustererKmeans() 
    with patch.object(sut,"clustering",new=np.array([0, 0, 1, 1, 3, 3, 3, 4, 5, 5])): 
     e = np.array([0, 1, 3, 4, 5]) 
     np.testing.assert_array_equal(np.array([0, 1, 2, 3, 4, 5]),sut.clusters) 

... но зачем использовать патч, когда питон дать вам простой и прямой способ сделать это?

Другой способ использовать макет рамки должны быть доверие numpy.unique и проверить, если свойство делать правильную работу:

@patch("numpy.unique") 
def test_gw_01(self, mock_unique): 
    sut = ClustererKmeans() 
    sut.clustering = Mock() 
    v = sut.clusters 
    #Check is called .... 
    mock_unique.assert_called_with(sut.clustering) 
    #.... and return 
    self.assertIs(v, mock_unique.return_value) 

    #Moreover we can test the exception 
    sut.clustering = None 
    self.assertRaises(Exception, lambda s:s.clusters, sut) 

Я извиняюсь за некоторые ошибки, но я не проверить код. Я вам сообщу, что я исправлю все как можно скорее.

+0

Я исправил тест для 'np.array' после прочтения http://stackoverflow.com/a/14921351/4101725 и http://stackoverflow.com/a/14249723/4101725 –

+0

Строка' r = ClustererKmeans.clusters (__get __ (sut)) 'дает мне ошибку:' NameError: name '__get__' не определен'. Конструктор здесь пуст, так как в моем вопросе я оставил все нерелевантные детали. На практике код более сложный. – physicalattraction

+0

Строка 'r = ClustererKmeans.clusters .__ get __ (sut)' работает так, как ожидалось. Спасибо за указание на это! – physicalattraction