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.

 Beneficis de les proves unitàries

modifica

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.

 Disseny de proves unitàries

modifica

Per tal de realitzar les provés unitàries sobre un mòdul necessitarem:

  • L'especificació dels mètodes del mòdul a treballar.
  • codi font del mètodes.

Algunes pautes per a realitzar un bon disseny de les proves unitàries:

  • Automatitzar l'execució de les proves unitàries.
  • Disponibilitat de realitzar les proves unitàries, per tal de poder executar-les davant una possible modificació del codi d'un mètode.
  • La prova unitària ha de poder cobrir la major quantitat de codi del mètode a revisar. Quan més baixa sigui la cobertura més codi es quedarà sense ser revisat.
  • L'execució d'una prova no ha d'afectar l'execució d'una altra. Al finalitzar l'execució d'una prova l'entorn ha de quedar com estava anteriorment.
  • Les relacions que puguin existir entre diferents mòduls han de ser simulades per evitar dependències entre mòduls i garantir una major qualitat de la prova unitària. “mocks objects”.
  • Important conèixer abans de dissenyar les proves unitàries quin serà l'objectiu de la prova.

 Desavantatges i limitacions de les proves unitàries

modifica
  • Les proves unitàries són molt eficaces per a detectar defectes en el codi però no la seva absència. Són més eficaces si es combinen amb altres tipus de proves de programari.
  • A vegades no és trivial anticipar tots els casos possibles d'entrada.
  • No permeten determinar problemes d'integració.
  • No descobriran tots els possibles defectes del codi.

 Exemple de prova unitària amb "JUnit"

modifica

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:

  • Cas normal: vector amb valors qualsevol:  [3, 7, 9, 8] -> 9
  • Quan el nombre major es troba al principi o al final de la llista [9, 7, 8] -> 9 ◦ [8, 7, 9] -> 9
  • Quan el nombre major està duplicat al vector [9, 7, 9, 8] -> 9
  • Quan només hi ha un element al vector [7] -> 7
  • Quan tots els nombres són negatius [-4, -6, -7, -22]-> -4

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}));
 }
}

 Frameworks per al desenvolupament de proves unitàries

modifica
  • JUnit:
  • TestNG: Creat per suplir algunes deficiències en JUnit.
  • JTiger: Basat en anotacions com el TestNG.
  • SimpleTest: Entorn de proves per aplicacions realitzades en PHP.
  • PHPUnit: Sistema per la realització de proves unitàries en PHP.
  • CPPUnit: Versió del framework per realitzar proves unitàries en C/C++.
  • NUnit: Versió del software per realitzar proves unitàries en .NET.
  • FoxUnit: Entorn de OpenSource de proves unitàries per Microsoft VisualFoxPro.
  • MOQ: Entorn per la creació din'amica d'objectes simuladors(mocks) «MOQ». 
  • QUnit: Llibreries per proves unitàries en JavaScript. Creat per la fundació JQuery, ha estat reescrita per ser independent de la llibreria JQuery.
  • libunittest: Llibreria portable per proves unitàries en C++ que utilitza el nou estàndard c++11.
  • CUnit: Entorn per escriure, administrar i executar test unitaris en C.

 

Referències

modifica
  1. Fowler, Martin. «Mocks aren't Stubs», 02-01-2007. [Consulta: 1r abril 2008].

Bibliografia

modifica