Doncs això, mai m'he mostrat partidari de cap metodologia de programació, ni tan sols de la programació orientada a objectes... però deu ser que em faig major ;) Anem a matar en un post dos pardals d'un tir. Anem a gastar una de les bases de les metodologies àgils (en realitat no té per què, es pot emprar en qualsevol metodologia) i anem a començar a veure com fer codi "multiplataforma".
Anem a gastar Visual Studio 2012. Creem una solució de Portable Class Library (en C#):
Creem una nova classe, Dau:
namespace RollDice
{
public class Dau
{
}
Sense cap mètode. Per què sense cap mètode? Ahí està la gràcia dels TDD (Test Driven Development, Desenvolupament Orientat a Test). Anirem omplint la classe segons fallen els tests.
Ara anem a afegir una nova solució, què serà de test c#:
Ens crearà una classe de test buida, li canviarem el namespace per a que siga el mateix que la classe dau:
[TestClass]
public class testDau
{
[TestMethod]
public void TestMethod1(){
}
}
De moment només ens interessa saber que el mètode que hi haja darrere de cada [TesMethod] Serà un test, ens eixirà a la finestra de tests (després veurem).
Què és el primer que hem de comprovar? Que li fa falta a un dau? El nombre de cares, no? Si no heu jugat a rol, possiblement no ho entendreu ;)
canviem el nom al test, per a que siga més encertat, creem un dau amb 4 cares i comprovem que realment les tinga quan es crea, per a això ens caldrà afegir una variable privada dau:
private Dau dau;
[TestMethod]
public void TestCares()
{
dau = new Dau(4);
Assert.AreEqual(4, dau.getCares);
}
Anem a pams, el primer que passa és què això no compila, la classe Dau està buida i no té cap mètode, fem que compile, afegim a la classe dau el constructor i la propietat cares:
public Dau(int cares)
{
getCares = cares;
}
public int getCares { get; private set; }
Ara que compila anem a veure que fa el test. Crea un dau de 4 cares, i el test passarà (les condicions de passar el test es fan amb les instruccions Assert) si efectivament el test és de 4 cares. Seleccionem el menu Test->Run All Test
Si el test passa veurem un check verd, si no passa, veureu una aspa roja,comproveu-ho posant:
Assert.AreEqual(5, dau.getCares);
Una vegada ja tenim comprovat que el constructor funciona, anem a acabar el dau. Què li falta? Tirar, l'opció de tirar. Abans de programar el codi, recordeu, hem de fer el test; afegim a la classe de test:
[TestMethod]
public void TestTirades()
{
dau = new Dau(10);
int tirada = dau.Tirada();
Assert.IsTrue(tirada <= 10);
Assert.IsTrue(tirada >= 1);
}
en este exemple, creem un dau de 10 cares, el llancem, i comprovem que la tirada estiga entre 1 i el nombre de cares. Com no compilarà, creem el mètode a la classe dau:
public int Tirada()
{
Random random = new Random();
return random.Next(1, getCares);
}
Vejam que el test passa. Òbviament este test, només serà vàlid per a 10 cares, res ens impedix fer este test:
[TestMethod]
public void TestTirades()
{
for (int i = 1; i <= 20; i++)
{
dau = new Dau(i);
int tirada = dau.Tirada();
Assert.IsTrue(tirada <= i);
Assert.IsTrue(tirada >= 1);
}
}
I així hauriem comprovat que els daus, almenys fins a 20 cares, funcionen ;). Doncs això és el TDD, primer realitzar quins tests ha de passar (incloent limits de vectors, entrades extranyes, si llança excepcions...)
A propers posts continuarem el projecte afegint múltiples configuracions per al projecte
Anem a gastar Visual Studio 2012. Creem una solució de Portable Class Library (en C#):
Creem una nova classe, Dau:
namespace RollDice
{
public class Dau
{
}
Sense cap mètode. Per què sense cap mètode? Ahí està la gràcia dels TDD (Test Driven Development, Desenvolupament Orientat a Test). Anirem omplint la classe segons fallen els tests.
Ara anem a afegir una nova solució, què serà de test c#:
Ens crearà una classe de test buida, li canviarem el namespace per a que siga el mateix que la classe dau:
[TestClass]
public class testDau
{
[TestMethod]
public void TestMethod1(){
}
}
De moment només ens interessa saber que el mètode que hi haja darrere de cada [TesMethod] Serà un test, ens eixirà a la finestra de tests (després veurem).
Què és el primer que hem de comprovar? Que li fa falta a un dau? El nombre de cares, no? Si no heu jugat a rol, possiblement no ho entendreu ;)
canviem el nom al test, per a que siga més encertat, creem un dau amb 4 cares i comprovem que realment les tinga quan es crea, per a això ens caldrà afegir una variable privada dau:
private Dau dau;
[TestMethod]
public void TestCares()
{
dau = new Dau(4);
Assert.AreEqual(4, dau.getCares);
}
Anem a pams, el primer que passa és què això no compila, la classe Dau està buida i no té cap mètode, fem que compile, afegim a la classe dau el constructor i la propietat cares:
public Dau(int cares)
{
getCares = cares;
}
public int getCares { get; private set; }
Ara que compila anem a veure que fa el test. Crea un dau de 4 cares, i el test passarà (les condicions de passar el test es fan amb les instruccions Assert) si efectivament el test és de 4 cares. Seleccionem el menu Test->Run All Test
Si el test passa veurem un check verd, si no passa, veureu una aspa roja,comproveu-ho posant:
Assert.AreEqual(5, dau.getCares);
Una vegada ja tenim comprovat que el constructor funciona, anem a acabar el dau. Què li falta? Tirar, l'opció de tirar. Abans de programar el codi, recordeu, hem de fer el test; afegim a la classe de test:
[TestMethod]
public void TestTirades()
{
dau = new Dau(10);
int tirada = dau.Tirada();
Assert.IsTrue(tirada <= 10);
Assert.IsTrue(tirada >= 1);
}
en este exemple, creem un dau de 10 cares, el llancem, i comprovem que la tirada estiga entre 1 i el nombre de cares. Com no compilarà, creem el mètode a la classe dau:
public int Tirada()
{
Random random = new Random();
return random.Next(1, getCares);
}
Vejam que el test passa. Òbviament este test, només serà vàlid per a 10 cares, res ens impedix fer este test:
[TestMethod]
public void TestTirades()
{
for (int i = 1; i <= 20; i++)
{
dau = new Dau(i);
int tirada = dau.Tirada();
Assert.IsTrue(tirada <= i);
Assert.IsTrue(tirada >= 1);
}
}
I així hauriem comprovat que els daus, almenys fins a 20 cares, funcionen ;). Doncs això és el TDD, primer realitzar quins tests ha de passar (incloent limits de vectors, entrades extranyes, si llança excepcions...)
A propers posts continuarem el projecte afegint múltiples configuracions per al projecte
Espere que hages llegit "Test-Driven Development by Example (Kent Beck)" o algún d'aquests i t'hages adonat que l'últim fragment de codi que has escrit és una burrada: els tests no han d'incloure lògica (for, while, switch i demés en un test són caca) i els tests només han de testejar una cosa (més d'un Assert per test també és caca)
ResponEliminaAixò sí, no em preguntes per què :P
Bo, en la pàgina de l'autor de Clean Code, Robert C. Martin, tenen un exemple, d'una partida de bolos on gasten lògica ;-)
ResponEliminaA banda, el tema de múltiples assert es deu a la limitació dels tests. No permet establir límits, comprovar si llança excepcions...
Tot això no lleva que tingues raó i el codi siga una merda.
Més menys per la meitat:
ResponEliminahttp://www.objectmentor.com/resources/articles/xpepisode.htm
public void testPerfectGame()
{
for (int i=0; i<12; i++)
{
g.add(10);
}
assertEquals(300, g.score());
assertEquals(10, g.getCurrentFrame());
}
Segur que a la pàgina de després diu: "mai feu això a casa, els tests no han d'incloure lògica i més d'un assert"... però no ho has llegit :D
ResponEliminaSegur, però ja saps... com a bon tertuliano pepero, cite el que em convé, ho descontextualitze i ignore la resta 😉
ResponElimina