Come popolare un container privato per il test dell'unità?

2

Ho una classe che definisce un contenitore privato (beh, __container per essere esatto poiché è python). Sto usando le informazioni all'interno di detto contenitore come parte della logica di ciò che fa la classe e ho la capacità di aggiungere / eliminare gli elementi di detto contenitore.

Per i test unitari, ho bisogno di compilare questo contenitore con alcuni dati. Quello i dati dipendono dal test fatto e quindi mettere tutto in setUp () sarebbe essere poco pratico e gonfio - in più potrebbe aggiungere effetti collaterali indesiderati.

Poiché i dati sono privati, posso solo aggiungere le cose al pubblico interfaccia dell'oggetto. Questo esegue codice che non deve essere eseguito durante un unit test e in alcuni casi è solo una copia e incolla da un altro test.

Attualmente sto prendendo in giro l'intero contenitore ma in qualche modo non si sente una soluzione elegante. A causa del lavoro con il frame mocking di Python ( mock ), questo richiede che il contenitore sia pubblico, quindi Posso usare patch.dict() . Preferirei mantenere privati questi dati.

Quale pattern è possibile utilizzare per riempire i contenitori senza utilizzare il metodo pubblico, quindi ho i dati da testare?

C'è un modo per farlo con il mock patch.dict() che ho perso ?

    
posta Sardathrion 15.11.2011 - 18:02
fonte

2 risposte

1

Fino a poco tempo fa, ti avrei solo indirizzato a molte altre domande esistenti che dicevano che generalmente non dovresti aver bisogno di accedere a cose private, al fine di scrivere test unitari - poiché l'intero punto di test è testare il interfaccia pubblica (e protetta).

Ad esempio, nella domanda come testare unitamente i metodi privati nei plugin jquery? , c'è questa risposta:

The same applies here as with any other language and testing privates: To test private methods, you should exercise them via the public interface. In other words, by calling your public methods, the private methods get tested in the process because the public methods rely on the privates.

Generally private methods are not tested separately from the public interface - the entire point is that they are implementation details, and tests should generally not know too much about the specifics of the implementation

Nel tuo caso specifico, dici:

Since the data is private, I can only add things via the public interface of the object. This run codes that need not be run during a unit test and in some case is just a copy and paste from another test.

Sarei cauto nell'avere test che evitino il codice che normalmente deve essere eseguito, per timore che i test vengano spuriati, a causa di una certa differenza tra il comportamento del test e il mondo reale.

Detto questo, recentemente ho saputo di un articolo davvero eccellente sulla scrittura di testsuite chiamato The Way of Testivus . È un PDF lungo solo 12 pagine e una lettura davvero facile e divertente.

Ciò che è rilevante qui è la sezione intitolata "A volte il test giustifica i mezzi" - nel contesto della violazione dell'incapsulamento per consentire il test. Lo consiglio vivamente.

(Un altro dei miei preferiti è "Un brutto test è meglio di nessun test.")

Quindi, nel tuo contesto, se decidi ancora di volere un modo diverso di impostare i dati esclusivamente per i test, potrebbe essere ragionevole aggiungere un metodo di setter pubblico, specificamente documentato come esistente solo per facilitare la scrittura dei test.

    
risposta data 16.11.2011 - 00:06
fonte
0

La convenzione per attributi privati è un singolo trattino principale; un doppio trattino di sottolineatura principale è protetto (utilizzerà il nome mangling per mantenere l'attributo univoco in sottoclassi).

class Test():
    _private = 1
    __protected = dict()
    __container = list()

Se privato è ciò che desideri veramente, rimuovi solo uno dei trattini bassi di sottolineatura e quindi l'accesso e la modifica di _container è facile-peasy.

Se protetto è davvero ciò che desideri, puoi comunque accedere a __container , ma dovrai manometterlo autonomamente se accedervi dall'esterno della classe. Usando la mia Test sopra per illustrare:

t = Test()
t.__Test_container.append("this is how it's done")
    
risposta data 11.01.2012 - 19:20
fonte

Leggi altre domande sui tag