Entra

View Full Version : [JAVA] JUnit: testare metodi privati


wingman87
05-03-2010, 18:03
Sto iniziando a usare JUnit e mi chiedevo come dovrei fare per testare i metodi privati delle mie classi. Tra l'altro come conviene organizzare i TestCase e i TestSuite?
In questo momento ho un progetto con i seguenti package:

mhs
mhs.card
mhs.hand

Tanto per cominciare volevo creare un TestCase per la classe Card che è contenuta in mhs.card
Ingenuamente ho creato un package test.mhs.card e vi ho messo la classe CardTest che ora testa i metodi pubblici di Card. Vorrei però avere anche la possibilità di testare i metodi privati, solo che ovviamente non ho accesso ad essi da una classe esterna. Come dovrei procedere?

banryu79
05-03-2010, 18:05
Stai usando un IDE particolare, che so, NetBeans?
Perchè in quel caso puoi semplicemente fare click tasto destro sulla classe per la quale vuoi creare lo unit test e nel menu contestuale trovi un voce apposita...
@EDIT: click destro -> Tools -> Create JUnit Test

wingman87
05-03-2010, 18:11
Grazie per la risposta. Sto usando Eclipse e c'è una voce simile ed è quella con cui ho creato la classe CardTest in test.mhs.card solo che come dicevo in questo modo non posso testare i metodi privati. In teoria dovrei fare una classe di test innestata in Card ma vorrei tenere separati i test da ciò che viene testato. Questo però è un vincolo che ingenuamente mi sono posto da solo, probabilmente bisogna ragionare in modo diverso. Tu in genere come procedi per creare le classi di test e dove le collochi nella struttura dei package?

banryu79
05-03-2010, 18:14
Per quanto riguarda lo unit test, testare i metodi privati della classe sotto test non ha molto senso.
Leggi questo (http://junit.sourceforge.net/doc/faq/faq.htm#tests_11).

@EDIT:
Premessa: io uso NetBeans.
In questo IDE, le classi per lo unit test delle classi dell'applicazione vengono automaticamente create nello stesso package della classe da testare.
L'IDE poi, nella vista ad albero del progetto, tiene separata la visualizzazione delle classi vere e proprio da quelle di test tramite due diversi nodi di espansione.

wingman87
05-03-2010, 18:22
Quindi molto probabilmente ho fatto un errore di progettazione... Ma è davvero così strano avere la necessità di testare un metodo privato se la progettazione è stata fatta come si deve? Potresti farmi qualche esempio?
E per quanto riguarda la posizione all'interno dei package secondo te va bene come ho fatto o è meglio mettere la classe di test e la classe testata nello stesso package?

banryu79
05-03-2010, 18:31
Quindi molto probabilmente ho fatto un errore di progettazione... Ma è davvero così strano avere la necessità di testare un metodo privato se la progettazione è stata fatta come si deve? Potresti farmi qualche esempio?

Non lo so, non ho una esperienza sufficiente in fatto di Unit Test per dire qualcosa con cognizione di causa.
Al massimo posso fare un considerazione: lo Unit Test di una classe testa esattamente un sola classe.
I metodi privati di quella classe sono prima o poi chiamati internamente dai metodi pubblici/protected*/default della classe (i metodi privati di una classe non vengono nemmeno ereditati da eventuali sotto-classi: dunque non possono che essere chiamati da altri metodi della classe stessa).
Testando tutta l'interfaccia pubblica/protected*/default della classe, in pratica, copri anche i metodi privati.

Quando poi un test fallisce, sai esattamente quale metodo (pubblico) lo ha fatto fallire (e anche perchè). Non penso quindi ci sia questa neccesità di testare esplicitamente i metodi privati. (Se proprio devi ti tocca usare gli escamotage descritti nella faq che ho linkato).

* vedi qua sotto:


E per quanto riguarda la posizione all'interno dei package secondo te va bene come ho fatto o è meglio mettere la classe di test e la classe testata nello stesso package?
Sempre in quella faq, domanda precedente a quella rimandata dal link.
Consigliano di metterli nello stesso package: in questo modo, dalla classe di test hai accesso anche hai metodi definiti con specificatore di accesso di default e protected (restano appunto "fuori portata" solamente quelli dichiarati private).
Il che giustifica anche il discorso fatto sopra.

wingman87
05-03-2010, 18:33
Grazie, sei stato gentilissimo e mi hai tolto tutti i dubbi.

banryu79
05-03-2010, 18:36
Grazie, sei stato gentilissimo e mi hai tolto tutti i dubbi.
You are welcome :)

khelidan1980
05-03-2010, 21:23
come appunto ti hanno detto se hai la necessità di testare metodi privati potrebbe essere che ci sia qualcosa da sistemare in fase di progettazione comunque non è detto, alcuni metodi privati possono essere molto complessi e richiedere di essere testati singolarmente, io in genere uso la reflection per testare il metodi privati, se cerchi su google trovi esempi da cui prender spunto, non è complicato

banryu79
05-03-2010, 22:25
...
io in genere uso la reflection per testare il metodi privati, se cerchi su google trovi esempi da cui prender spunto, non è complicato

Posto un link (è il mio hobby preferito) ad un articolo interessante (http://www.artima.com/suiterunner/private.html) che illustra pro/contro di quattro possibili soluzioni per testare metodi privati:

* Don't test private methods.
* Give the methods package access.
* Use a nested test class.
* Use reflection.