Les proves unitàries o proves de components són un tipus de proves de programari que consisteixen a realitzar proves sobre els components o unitats més petits del codi font d'una aplicació o d'un sistema (entès com a unitat la part provable més petita d'una aplicació). Generalment, en programació estructurada és un mètode o rutina, en programació procedimental és una funció o procediment, i en programació orientada a objectes acostuma a ser un mètode o una classe. Són proves que depenen de la tecnologia emprada, i típicament, les duen a terme els mateixos equips de desenvolupament.
Idealment, cada cas de prova és independent dels altres: substituts com stubs, objectes simulats,[1] o un arnès de proves es poden utilitzar per ajudar a provar un mòdul de forma aïllada.
La finalitat de les proves unitàries és comprovar el correcte funcionament d'un mòdul de codi, per tal de garantir que cadascun dels mòduls funcionen correctament per separat. A posteriori, mitjançant les proves d'integració es podrà comprovar el funcionament del sistema en conjunt.
Facilitat per trobar errors:
Al treballar el sistema amb les proves unitàries treballem en un context més acotat, per tant, la localització d'errors és molt més senzilla que si treballem en un context global del programa. Aquest fet, ens proporciona que el rendiment d'errors localitzats per temps invertit sigui major. Podem trobar errors en el codi realitzat pel desenvolupador o errors en l'especificació del mòdul a provar.
Es permet detectar de forma efectiva la injecció de defectes durant fases posteriors del disseny o manteniment del sistema.
Reestructuració del codi:
Si disposem de proves unitàries per a tots els mètodes i funcions del sistema, cada cop que el programador vulgui realitzar un canvi sobre aquests, podrem detectar si els nous canvis produeixen fallades. En aquest cas, els programadors podran refactoritzar el codi modificant l'estructura interna d'aquest sense alterar el seu comportament.
Simplifica el procés d'integració dels mòduls:
El mètode de realitzar proves en primer lloc sobre els mòduls per separat, simplifica i facilita les proves d'integració dels mòduls del sistema. D'aquesta forma reduïm la probabilitat de trobar errors en el procés d'integració.
Documentació del codi:
Les proves unitàries proporcionen informació del codi, com la seva funcionalitat i la seva especificació. Aquest fet facilita la comprensió per als programadors sobre el funcionament de la unitat.
Les proves unitàries poden proporcionar informació sobre les característiques que són fonamentals per al correcte funcionament del codi, i a més a més ens pot informar sobre els usos inadequats que es poden donar sobre el codi.
En definitiva si realitzem les proves unitàries abans d'implementar el codi, aquestes actuen com un document de disseny que especifiquen la forma i el comportament d'una solució desitjada, però no els detalls d'implementació del qual s'encarregarà el programador. Per tant, la implementació realitzada pel programador no passarà les proves si no s'implementa una solució d'acord amb el'disseny de les proves.
Separació de la interfície i la implementació
Generalment una classe sol tenir associada una o més classes, per tant, alhora de realitzar proves sobre una classe podem estar provant altres classes associades. Per exemple, pot haver-hi classes que estan relacionades amb una base de dades. Si volem realitzar proves unitàries haurem d'aïllar aquesta relació.
Per aquest motiu els programadors hauran de crear una interfície abstracta entorn de les consultes a la base de dades, per tal d'implementar aquesta interfície amb el seu propi mock object.
Aquests objectes són utilitzats per a resoldre el problema dels objectes interdependents, és a dir, imita el comportament de l'objecte real d'una forma controlada retornant resultats determinats i d'implementació directa.
D'aquesta manera aconseguim una menor dependència entre les classes per poder realitzar les proves unitàries de major qualitat i aïllament sobre la classe.
Per tal de realitzar les provés unitàries sobre un mòdul necessitarem:
Algunes pautes per a realitzar un bon disseny de les proves unitàries:
JUnit es tracta d'un conjunt de biblioteques que són utilitzades en programació per realitzar proves unitàries d'aplicacions Java.
Disposem d'una classe anomenada “MajorNumero”, la qual disposa d'un mètode anomenat “obtenirMajor”, el qual pren un array de nombres enters com a argument i retorna el major valor trobat a l'array.
package elements;
public class MajorNumero {
/* Retorna l'element major d'una seqüència d'enters
@param Un vector d'enters
@return l'enter de major valor del vector */
public static int obtenirMajor(int llista[]){
int max=llista[0];
int i;
for(i=0;i<llista.length-1;i++){
if(llista[i] >max) max = llista[i];
}
return max;
}
}
A continuació, s'han de decidir i dissenyar quins tipus de proves unitàries es poden realitzar sobre aquest mètode:
Codi de les proves unitàries realitzades sobre el mètode "obtenirMajor":
“assertEquals (valor_esperat, valor_real)”
package elements;
import junit.framework.TestCase;
public class MajorNumeroTest extends TestCase{
public void testSimple(){
assertEquals(9,MajorNumero.MajorNumero(new int[] {3,7,9,8}));
}
public void testOrden(){
assertEquals(9, MajorNumero.MajorNumero(new int[] {9, 7, 8}));
assertEquals(9, MajorNumero.MajorNumero(new int[] {7, 9, 8}));
assertEquals(9, MajorNumero.MajorNumero(new int[] {7, 8, 9}));
}
public void testDuplicats() {
assertEquals(9, MajorNumero.MajorNumero(new int[] {9, 7, 9, 8}));
}
public void testNomesUn() {
assertEquals(7, MajorNumero.MajorNumero(new int[] {7}));
}
public void testTotsNegatius() {
assertEquals(-4, MajorNumero.MajorNumero(new int[] {-4, -6, -7, -22}));
}
}