2015-08-19 14 views
12

Mi chiedevo se è possibile prendere in giro una funzione C utilizzando la libreria Python mock e come?È possibile simulare una funzione C usando python?

Per eseguire un test di unità per una funzione C in Python, utilizzo la libreria condivisa, ma non posso prendere in giro una funzione per passare il test. I test funzionano bene quando non è necessario utilizzare il mock.

Quindi la mia domanda è: è possibile prendere in giro una funzione C usando Python mock e come?

Ecco un esempio di codice sorgente.

//read_sensor.c 
    #include <stdint.h> 
    #include "read_sensor.h"   
    uint8_t read_sensor (void) 
    { 
     return 0xff; 
    } 

//event_report.c 
    include <stdint.h> 
    #include <string.h> 
    #include "event_report.h" 
    #include "read_sensor.h" 


    #define TRUE 1 
    #define FALSE 0 

    extern char status ; 
    extern uint8_t flag; 

    void read_distance(void) 
    { 
     uint8_t count; 
     uint8_t value; 
     uint8_t flag_count = 0; 
     for (count = 0; count < 3; count ++) 
     { 
      value = read_sensor(); 
      if (value < 100) 
      { 
       flag_count++; 
      } 
     } 

     if (flag_count == 3) 
     { 
      flag = TRUE; 
     } 
     else 
     { 
      flag = FALSE;  
     }  
    } 

e il test è qui

import ctypes 
from ctypes import * 
import mock 
import unittest 

TRUE = 1 
FALSE = 0 

class TestClass(unittest.TestCase): 

    def setUp(self): 
     print "\nSetUp\n" 
     self.event=ctypes.CDLL('d:/test_pytest/test_sensor_report/event_report.so') 

    def tearDown(self): 
     print "tearDown\n" 


    def test_1_flag_should_be_true_when_readed_distance_is_0(self): 
     expected_flag = TRUE 

     self.event.read_sensor = MagicMock(return_value = 0) 

     #calling function under test 
     result = self.event.read_distance() 
     print result 

     #testing assertion 
     assert expected_flag == result 

Dopo aver ispezionato con inspect.getmembers() ottengo il seguente:

[('_FuncPtr', <class 'ctypes._FuncPtr'>), ('__class__', <class 
'ctypes.CDLL'>), ('__delattr__', <method-wrapper '__delattr__' of 
CDLL object at 0xffa87eec>), ('__dict__', {'_FuncPtr': <class 
'ctypes._FuncPtr'>, '_handle': 1690304512, '_name': 
'd:/test_pytest/test_sensor_report/event_report.so'}), 
('__doc__', "An instance of this class represents a loaded 
    dll/shared\n library, exporting functions using the standard C 
    calling\n convention (named 'cdecl' on Windows).\n\n The 
    exported functions can be accessed as attributes, or by\n 
    indexing with the function name. Examples:\n\n <obj>.qsort -> 
    callable object\n <obj>['qsort'] -> callable object\n\n 
    Calling the functions releases the Python GIL during the call 
    and\n reacquires it afterwards.\n "), ('__format__', 
    <built-in method __format__ of CDLL object at 0xffa87eec>), 
    ('__getattr__', <bound method CDLL.__getattr__ of <CDLL 
    'd:/test_pytest/test_sensor_report/event_report.so', handle 
    64c00000 at ffa87eec>>), ('__getattribute__', <method-wrapper 
     '__getattribute__' of CDLL object at 0xffa87eec>), 
    ('__getitem__', <bound method CDLL.__getitem__ of <CDLL 
    'd:/test_pytest/test_sensor_report/event_report.so', handle 
    64c00000 at ffa87eec>>), ('__hash__', <method-wrapper 
     '__hash__' of CDLL object at 0xffa87eec>), ('__init__', 
      <bound method CDLL.__init__ of <CDLL 
      'd:/test_pytest/test_sensor_report/event_report.so', 
      handle 64c00000 at ffa87eec>>), ('__module__', 'ctypes'), 
     ('__new__', <built-in method __new__ of type object at 
      0x3d35b600>), ('__reduce__', <built-in method __reduce__ of 
       CDLL object at 0xffa87eec>), ('__reduce_ex__', <built-in 
        method __reduce_ex__ of CDLL object at 0xffa87eec>), 
       ('__repr__', <bound method CDLL.__repr__ of <CDLL 
       'd:/test_pytest/test_sensor_report/event_report.so', 
       handle 64c00000 at ffa87eec>>), ('__setattr__', 
        <method-wrapper '__setattr__' of CDLL object at 
        0xffa87eec>), ('__sizeof__', <built-in method 
         __sizeof__ of CDLL object at 0xffa87eec>), 
        ('__str__', <method-wrapper '__str__' of CDLL object 
        at 0xffa87eec>), ('__subclasshook__', <built-in 
         method __subclasshook__ of type object at 
         0xffae8204>), ('__weakref__', None), 
        ('_func_flags_', 1), ('_func_restype_', <class 
          'ctypes.c_long'>), ('_handle', 1690304512), 
        ('_name', 
         'd:/test_pytest/test_sensor_report/event_report.so')] 
+1

Puoi fornire uno snippet del codice per vedere come stai includendo le tue librerie C? –

+1

l'ho aggiunto alla domanda originale –

+0

Ciò sarebbe teoricamente possibile, almeno se la funzione C non è stata dichiarata "statica". Non sono sicuro se sia fatto da una qualsiasi struttura di derisione. –

risposta

1

Se deridere che si fa finta che sia affidabile. O almeno non testare funzionalità testate nel test usando la simulazione.

Nessun punto nel deridere esattamente la funzione C, non è necessario caricare l'oggetto SO.

Mock self.event e aggiungere l'istanza di Mock "read_sensor" ad esso, utilizzare la simulazione.

Problemi correlati