Unit Testing: otra manera de testear
Todos los programadores sabemos deberiamos saber que si no probas lo que desarrollas tus usuarios lo harán por vos.
El unit testing (prueba unitaria) es un tipo de testing automático que se hace programando unas rutinas u objetos que controlan si la rutina y/u objeto que programamos funciona como lo esperabamos.
Por ejemplo, una función que nos devuelva la raíz de una función lineal, donde el primer parámetro sería el término lineal y el segundo el término independiente, tendría las siguientes pruebas:
if( funcion_lineal(1, 0) != 0 ){
printf("no funciona!");
}
if( funcion_lineal(2, 1) != -0.5 ){
printf("no funciona!");
}
Este es un ejemplo sencillo, ¿pero cuantos de ustedes se acordaron que si el término lineal es 0 y el independiente es distinto de 0, no tenemos raíz? Ese es otro test que deberíamos tener.
if( funcion_lineal(0, 3) != false ){
printf("no funciona!");
}
Al tener algunos tests podemos programar la rutina y saber si funciona de manera instantánea sin ir probando sus entradas de manera manual, por que ya lo hicimos antes.
Con un código orientado a objetos el código es distinto pero el concepto es el mismo.
Las claves del unit testing son que sean:
- Fácil de hacer
- Automáticos
- Simple de ejecutar (para ejecutarlos continuamente)
Ventajas
¿Y donde están las ventajas de este tipo de testing? Bueno si arreglamos un bug, y desarreglamos otros 2 módulos que funcionaban bien, nos daríamos cuenta de manera inmediata. También se puede usar cuando tenemos un código viejo (legacy code) que sabemos que funciona pero necesitamos cambiarlo sin agregarle bugs (esto es refactoring).
Otra ventaja es que nos ayuda a tener un diseño prolijo de la aplicación ya que si para testear cada módulo (en este caso usamos módulos como conjunto de rutinas u objetos) necesitamos de otros módulos sabemos que la aplicación no es ortogonal, es decir que sus módulos no son independientes.
Además los Unit Testing pueden ser usados como documentación para saber cómo deben usarse los módulos.
Hacer Unit Testing no quiere decir que no haya que hacer beta testing (el testing que conocemos todos). Es imposible que el Unit Testing nos demuestre que el código no tiene errores, sirve para demostrarnos que no tiene esos errores y no los va a volver a tener (a menos que alguien lo rompa y no lo arregle :P).
Desventajas
Una desventaja es la cantidad de código que debemos escribir. En el ejemplo de arriba la funcion sería:
int function function_lineal(int terminoLineal, int terminoIndependiente){
return (-1 * terminoIndependiente) / terminoLineal;
}
Y como vimos antes las pruebas son muchas más que una sola línea. A veces nos puede resultar pesado mantener los tests, no nos olvidemos que cuando haya que cambiar código también tenemos que cambiar los tests.
También tenemos problemas si los métodos que tenemos que ejecutar son muy pesados, si pasar un unit testing completo nos lleva más de 2 horas es muy improbable que los programadores lo hagan seguido.
xUnit
En el ejemplo anterior en realidad parece tedioso hacer tanto código para controlar si funciona bien algo. Y es cierto, es tedioso. Pero existen varios frameworks para muchos lenguajes de programación que hacen que hacer pruebas unitarias sean mucho más sencillo, los llamados xUnit.
xUnit viene de SUnit (desarrollado para SmallTalk) el primer framework desarrollado por Kent Beck (autor del primer paper sobre unit testing) y el más popular JUnit (desarrollado para Java).
Un ejemplo de JUnit siguiendo con el mismo ejemplo anterior pero adaptado a objetos es el siguiente:
public class FuncionesMatematicas extends TestCase
{
protected FuncionesMatematicas funcionesMatematicas;
public void setUp()
{
// inicializamos el objeto, creando su singleton
funcionesMatematicas = FuncionesMatematicas::getInstance();
}
public void testFuncionLineal()
{
// probamos si el metodo devuelve 0
assertEquals ("Raiz Lineal f(x) = x", 0, funcionesMatematicas.getRaizLineal(1, 0));
// probamos si el metodo devuelve -0.5
assertEquals ("Raiz Lineal f(x) = 2x+1", -0.5, funcionesMatematicas.getRaizLineal(2, 1));
// probamos si el metodo devuelve false
assertFalse ("Raiz Lineal sin raiz", funcionesMatematicas.getRaizLineal(0, 3));
}
}
Cada clase es un TestCase y el conjunto de TestCase son TestSuite.
Ya dijimos que es muy importante que sean fáciles de ejecutar, bueno muchos de estos frameworks se ejecutan con una sola llamada en consola o incluso desde nuestro IDE, y nos retorna los assert que pasaron y los que no en cuestión de minutos.
También nos brindan la posibilidad de ejecutar un TestCase, un TestSuite o varios.
Test Driven Development
TDD (Test Driven Development) es una técnica usada en la metodología eXtreme Programming (Programación Extrema) que consiste en programar primero los tests y después lo que estamos testeando (si es así, no estoy delirando). En TDD se sigue un ciclo de desarrollo que consiste en:
- Agregar un test
- Comprobar que falla
- Escribir código para que pase el test (el objetivo es que pase el test no debe estar prolijo ni nada si no se quiere)
- Probar que pasa el test
- Refactoring (ahora si limpiamos el código que habíamos escrito antes)
- Repetir
TDD nos ayuda a crear buenas interfaces de nuestras clases al pensar primero en cómo vamos a llamarlas en vez de cómo funcionarían por dentro. Es muy buena cuando tenemos casos de uso (o similares) donde sabemos bien de antemano qué es lo que tenemos que cumplir.
Mock Objects
Supongamos que tenemos que desarrollar un sistema que lea las RSS de varios portales de noticias y las muestre en un solo sitio y nos diga cuales RSS no han podido ser leídos. Pero, ¿para qué hacer una clase que lee RSS y lo parsea si podemos usar la de Zend Framework (Zend_Feed)?. Solamente nos toca hacer una clase que haga lo siguiente:
class LectorRss{
public function leerRss(array $direccionesRss){
foreach($direccionesRss as $direccionRss){
try{
$rss = Zend_Feed::import($direccionRss);
foreach($rss as $item){
$this->addTitular($item->title, $item->link);
}
$this->addRssCargados($direccionRss);
}catch(Exception $e){
$this->addRssConErrores($direccionRss);
}
}
}
}
Ahora bien, si queremos hacer un test, no podemos controlar cuando un RSS se carga y cuando no. Además tardaría mucho en leer cada feed y procesarlo y (¡volvemos a repetir!) los tests deben ser rápidos (¡sino nadie los va a hacer!, seguimos repitiendo). En esos momentos es donde entran en juego los Mock Objects (para ilustrar el concepto usamos SimpleTest, los otros frameworks no funcionan igual).
class LectorRssTest extends UnitTestCase
{
public function testLeerRss()
{
// Creamos la clase Mock
Mock::generate('Zend_Feed');
$mockZendFeed = new MockZend_Feed();
$mockZendFeed->setReturnValue('import', false);
// La primera vez que se use devolvera $datos
$mockZendFeed->setReturnValue(0, 'import', $datos);
// La segunda devolvera false
$mockZendFeed->setReturnValue(1, 'import', false);
// Esta vez devolvera $otrosDatos
$mockZendFeed->setReturnValue(2, 'import', $otrosDatos);
$lectorRss = new LectorRss();
$lectorRss->leerRss(array("feed1.xml","feed2.xml","feed3.xml"));
$this->assertEqual("Total leidos bien", $lectorRss->getTotalCargados(), 2);
$this->assertEqual("Total con error", $lectorRss->getTotalConErrores(), 1);
}
}
Conclusión
El unit testing es una buena y compleja práctica que nos ayuda a mantener el código prolijo porque nos permite tocar código sin tener miedo a romper algo. En mi caso lo uso siempre que hago una clase o paquete que quiero reutilizar muchas veces (por ejemplo una clase de acceso a Base de Datos), porque puedo justificar el costo de hacerlo y las clases que voy a reutilizar deben tener la mayor calidad posible y la interfaz más fácil para que se use. Si tienen una oportunidad pruebenlo.
Actualización: cerre los comentarios porque me canse del SPAM, cualquier comentario relacionado por favor dejenlo en SimpleTest Cheatsheet
Tags: mock objects, tdd, testing, unit testing, xunit

12-06-2008 at 13:58
[…] dejo el Cheat Sheet (a.k.a. Chuleta, a.k.a. machete) de SimpleTest, una clase para hacer Unit Testing en […]
25-05-2009 at 16:03
Hola Rodrigo:
Te escribo para consultarte, como logro probar las funcionalidades javaScript dentro de un browser tal como MOZILLA, IE, OPERA, ETC, pero quisiera pobrar el de todos, usando el simpletest, de antemano te agradesco la respuesta y el tiempo para responder.
Ricardo.
26-05-2009 at 11:08
Hola Ricardo, para probar funcionalidades del browser te recomiendo usar Selenium http://seleniumhq.org/
Nunca hice UnitTests sobre JavaScript así que no te puedo recomendar ningún framework en especial, aca tenés un listado http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#JavaScript para buscar el que mas se adapte a tus necesidades.
Saludos
26-05-2009 at 12:53
te agradezco Rodrigo la rápida respuesta, más bien tengo una duda, al probar una función que contiene parámetros por ejemplo:
function pureba_de_funcion($valor_dado= ‘ ‘ ){
global $dato_dado;
condicones si( $valor_dado = ”) {
return $Globals[”_id”];
} sino {
aqui se hace una pequeña consulta a base de datos
tales como
$valor_tabla[’nombre’] =$resultado[’nombre’];
…
return $valor_tabla;
}
return false;
}
}
en las anteriores funciones no tenían parámetros en esta si, quisiera saber como realizar una prueba cuando la función pide parámetros.
gracias !!
26-05-2009 at 14:06
No entiendo bien tu duda. ¿Estas usando algún framework para testear?
26-05-2009 at 14:35
estoy usando el SimpleTest, lo que sucede necesito probar funciones que contienen parámetros que son jalados de una base de datos, en pocas palabras quiero saber si la función trabaja bien o no.
26-05-2009 at 14:46
Ok, ahore te entendi. Si usas un objeto o una clase para conectarte y ejecutar consultas a una base (por ejemplo Zend_Db, el package de PEAR DB, o cualquier otra) lo que tenés que hacer es crear un “mock” de esa clase. En este post tenés un ejemplo de un mock, en el sitio de SimpleTest también tenés un buen tutorial.
Si no tenes una clase para conectarte (aunque te recomiendo que uses una) vas a tener que crear base de datos de prueba y llenarla con los datos de pruebas.
26-05-2009 at 14:47
El tutorial de Mock objects con SimpleTest esta en http://simpletest.sourceforge.net/en/mock_objects_documentation.html
26-05-2009 at 15:12
Yo quisiera poder probar esta función
function api_clean_anonymous($db_check=false) {
global $_user;
if (api_is_anonymous($_user[’user_id’],$db_check)) {
unset($_user[’user_id’]);
api_session_unregister(’_uid’);
return true;
} else {
return false;
}
para probar esta funcion estoy haciendo algo como esto :
function testApiCleanAnonymous()
{
$res = api_clear_anonymous($db_check=false);
return $this->assertFalse($res);
}
ahora me sale que pasa la prueba, pero creo que no es algo que me convence mucho.
Ahora por favor, como podría hacer una verdadera prueba con esto ??
te lo agradeceria mucho
26-05-2009 at 17:27
Mas alla de una decisión de diseño de no usar funciones y variables globales, lo que haría es probar las funciones api_is_anonymous (para los cuatro casos, cuando la base sea true y devuelva true, etc) y api_session_unregister (para los casos que desregistre o no un usuario) y luego probaría api_clean_anonymous. En este último caso
function testApiCleanAnonymous()
{
global $_user;
$_user[’user_id’] = 1;
$res = api_clear_anonymous($db_check=false);
$this->assertFalse($res);
$this->assertTrue(isset($_user[’user_id’] ));
// ahora irian el resto de los casos
}
26-05-2009 at 18:20
Hola albo, te agradezco mucho que me ayudes con esto de las pruebas con el Simple test, sabes soy nuevo en todo esto, trato de entender más a fondo, se que con practica lo haré, pero hay cositas que quizás sean tontas para ti, pero prefiero a pasar la vergüenza de preguntar a quedarme con la duda de no poder entenderlo y resolverlo.
Ahora te quiero mostrar la prueba que hice al “api_is_anonymous” y me gustaria que me dijeras si esta bien o me equivoque en algo.
weno la funcion api_is_anonymous esta compuesta por:
function api_is_anonymous($user_id=null,$db_check=false) {
if(!isset($user_id)) {
$user_id = api_get_user_id();
}
if($db_check) {
$info = api_get_user_info($user_id);
if($info[’status’] == 6) {
return true;
}
} else {
global $_user;
if (!isset($_user)) {
//in some cases, api_set_anonymous doesn’t seem to be
//triggered in local.inc.php. Make sure it is.
//Occurs in agenda for admin links - YW
global $use_anonymous;
if (isset($use_anonymous) && $use_anonymous == true) {
api_set_anonymous();
}
return true;
}
if (isset($_user[’is_anonymous’]) and $_user[’is_anonymous’] === true) {
return true;
}
}
return false;
y esta es mi prueba de api_is_anonymous, me gustaria poder saber si esta bien o me faltaron algunas cosas.
function testApiIsAnonymous(){
$_user[’user_id’]=1;
$res=api_is_anonymous($user_id=null, $db_check=false);
$this->assertfalse($res);
$this->assertfalse(isset($_user_id));
$this->assertTrue($db_check=true);
$this->asserttrue(isset($res));
}
el resultado que me mando es el siguiente:
OK
Test cases run: 1/1, Passes: 4, Failures: 0, Exceptions: 0
gracias !!
27-05-2009 at 11:54
Hola Ricardo, en principio quiero decirto que me parece perfecto que no tengas vergüenza, me encanta poder ayudarte porque estoy seguro que así también aprendo yo (espero que te sea realmente útil).
Sobre el código, aparentemente esta todo bien. Lo que podrías hacer es probar si falla. Eso siempre es importante. Es decir comentá/borrá todo el funcionamiento de api_is_anonymous y comprobá que falla para los casos esperados (excepto obviamente en assertFalse), es tan importante saber que falla cuando tiene que fallar como que funciona cuando tiene que funcionar.
No te vuelvas loco buscando todos los casos posibles, dejalos que vayan surgiendo.
Un último consejo, de obsesivo que soy solamente jaja, fijate de poner los métodos siempre igual no assertrue y asserTrue, y esta última manera de llamarlo es la que te recomiendo por mas que las dos funcionen.
27-05-2009 at 14:17
Buenos días mi querido amigo Albo, agradezco tu apoyo y tu ayuda con respecto a las pruebas con el Simple Test, muchas gracias por todo, no sabes lo valioso que me resultan tus consejos, mas que amigo creo que seras mi maestro jedi y yo tu padawan, n_n jajaja
Bueno volviendo al tema, tengo una super duda con respecto a una funcion que creo que es muy complicada, pero que aun no encuentro la manera de probar totalmente su funcionalidad, me gustaria un apoyo en esta parte:
function api_display_tool_view_option() {
if (api_get_setting(’student_view_enabled’) != “true”) {
return ”;
}
$output_string=”;
$sourceurl = ”;
$is_framed = false;
// Exceptions apply for all multi-frames pages
if (strpos($_SERVER[’REQUEST_URI’],’chat/chat_banner.php’)!==false) { //the chat is a multiframe bit that doesn’t work too well with the student_view, so do not show the link
$is_framed = true;
return ”;
}
// Uncomment to remove student view link from document view page
if (strpos($_SERVER[’REQUEST_URI’],’document/headerpage.php’)!==false) {
$sourceurl = str_replace(’document/headerpage.php’,'document/showinframes.php’,$_SERVER[’REQUEST_URI’]);
//showinframes doesn’t handle student view anyway…
//return ”;
$is_framed = true;
}
// Uncomment to remove student view link from document view page
if (strpos($_SERVER[’REQUEST_URI’],’newscorm/lp_header.php’)!==false) {
if (empty($_GET[’lp_id’])) {
return ”;
}
$sourceurl = substr($_SERVER[’REQUEST_URI’],0,strpos($_SERVER[’REQUEST_URI’],’?'));
$sourceurl = str_replace(’newscorm/lp_header.php’,'newscorm/lp_controller.php?’.api_get_cidreq().’&action=view&lp_id=’.intval($_GET[’lp_id’]).’&isStudentView=’.($_SESSION[’studentview’]==’studentview’?'false’:'true’),$sourceurl);
//showinframes doesn’t handle student view anyway…
//return ”;
$is_framed = true;
}
// check if the $_SERVER[’REQUEST_URI’] contains already url parameters (thus a questionmark)
if (!$is_framed) {
if (!strstr($_SERVER[’REQUEST_URI’], “?”)) {
$sourceurl = api_get_self().”?”.api_get_cidreq();
} else {
$sourceurl = $_SERVER[’REQUEST_URI’];
//$sourceurl = str_replace(’&’, ‘&’, $sourceurl);
}
}
if(!empty($_SESSION[’studentview’])) {
if ($_SESSION[’studentview’]==’studentview’) {
// we have to remove the isStudentView=true from the $sourceurl
$sourceurl = str_replace(’&isStudentView=true’, ”, $sourceurl);
$sourceurl = str_replace(’&isStudentView=false’, ”, $sourceurl);
$output_string .= ‘‘.get_lang(”CourseManagerview”).’‘;
} elseif ($_SESSION[’studentview’]==’teacherview’) {
//switching to teacherview
$sourceurl = str_replace(’&isStudentView=true’, ”, $sourceurl);
$sourceurl = str_replace(’&isStudentView=false’, ”, $sourceurl);
$output_string .= ‘‘.get_lang(”StudentView”).’‘;
}
} else {
$output_string .= ‘‘.get_lang(”StudentView”).’‘;
}
echo $output_string;
}
he estado probando con muchas cosas, pero no me convence muy bien el metodo, que me sugieres y como hacerlo, a partir de esta función, se generan muchas funciones muy parecidas, y como que comienzo a “volar” en esta parte.
Por tu ayuda; de manera anticipada; gracias.
Ricardo Padawan
27-05-2009 at 14:33
otra pregunta asi a al volada, cuando una función tiene un parámetro, por ejemplo:
function api_display_debug_info($debug_info)
{
$message = “Debug info“;
$message .= $debug_info;
Display :: display_normal_message($message);
}
y no me dice nada sobre el valor que toma la variable, pero me dicen que el $debug_info es un parámetro string, como podría usarlo en la función prueba sin darle un valor, ya que al crear la prueba el $debug_info me sale como dato sin valor declarado…(no es un error, pero esa variable no tiene un valor o quizas sea un dato por default, no lo se).
aunque parece que esta declarado como $message, tendria que ver de donde viene ese $message ?
27-05-2009 at 16:26
Hola Ricardo, mira esto que te voy a decir es mas que nada un pensamiento mío (aunque es posible que lo haya leído en algún libro de un Jedi real jeje):
“Cuando te cuesta testear algo es porque esta mal hecho”.
Te explico un poco mas de esto. Hay algo que va de la mano de los UnitTest y es el Refactoring. El refactoring es básicamente cambiar código sin modificar su comportamiento, podría decirse “limpiar código”. En los casos donde se me complicó hacer UnitTest eran clases que estaban muy acopladas a otras o códigos demasiado grandes que tenían más de una responsabilidad en su interior. Eso es un signo de que tenés que hacer refactoring (aunque surge un problema del huevo y la gallina, porque para hacer refactoring tenés que tener UnitTest).
También tenés que tener en cuenta que cuando dependes de métodos estáticos o funciones y no tenés manera de hacer un mockeo (esto es Mock Objects) como te dice SimpleTest tenés que hacer tu propio mockeo, por ejemplo:
class Display{
static public $message;
static public function display_normal_message($message)
{
self::$message = $message;
}
}
public function testApiDisplayDebugInfo()
{
$mensaje = crearTextoAleatorio(); // siempre que puedas, te conviene probar con valores creados al azar
api_display_debug_info($mensaje);
$recibido = Display::$mensaje;
$this->assertEquals($recibido, “Debug info”.$mensaje);
}
28-05-2009 at 12:35
Hola albo, te saludo y de paso te piso una pequeña ayuda, no se si pudieras ayudarme hacer unas pruebas sobre una clase con varias funciones, me gustaría que me guiaras y me enseñaras algunos trucos, en las que podría aplicar a las pruebas, dime que día tienes tiempo y nos conectamos vía msn, gmail, yahoo o lo que desees y realizamos unas pequeñas pruebas para ver si lo que hice estaba bien o en otro caso, para aprender mas cosas con el simple Test, te agradezco de antemano y saludos. si deseas me puedes enviar un correo a ricardo.rodriguez {at} dokeos(.)com o sino a richi06031983 {at} gmail(.)com
Ricardo
29-05-2009 at 10:56
Hola Ricardo, mira lo único que te puedo decir es que esto mucho prueba/error. No lo vas a hacer bien al primer momento, como durante cualquier aprendizaje. Lo que tenés que hacer es intentarlo, equivocarte y corregirlo.
Saludos
29-05-2009 at 14:10
uhmm… si yo se que tienes razón, pero solo trataba de aprender de una manera más clara con tus consejos, mas bien lo siento si comencé a preguntarte muchas cosas… se que debes estar muy ocupado.
Tratare de averiguar por mi propia cuenta y como dices, cometeré errores pero así se aprende, gracias por el super consejo.
29-05-2009 at 16:57
alert(”probandoUnjeccion”);
29-05-2009 at 16:58
bien aaah… la tienes bien cuidado…
02-06-2009 at 12:24
Hola albo, como estas, me preguntaba si me podrías ayudar en algunas cosas:
function api_get_current_access_url_id()
{
$access_url_table= Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
$path = api_get_path(WEB_PATH);
$sql = “SELECT id FROM $access_url_table WHERE url = ‘”.$path.”‘”;
$result = api_sql_query($sql);
if (Database::num_rows($result)>0) {
$access_url_id = Database::result($result, 0, 0);
return $access_url_id;
} else {
return -1;
}
}
supuestamente me tiene que devolver el id de la url de acceso de instalación o algo parecido, por favor si me pudieras ayudar, gracias
03-06-2009 at 15:49
Hola Ricardo, no creo que te pueda aportar mucho mas en este ejemplo que en los anteriores que me has pedido. Saludos.
04-06-2009 at 11:27
Me gustaría que me pudieras ayudar en todo lo que sepas, quiero aprender a usar el simple test de manera óptima y saber como poder hacer mejor las pruebas, tu ayuda en lo más mínimo, me aportaría muchas cosas.
09-06-2009 at 17:25
Hol albo, tengo una pregunta, cuando la funcion return un void o un string que tipo de assert devemos colocarle.. ?¿? o solamente es con el assertTrue y el assertFalse?? a ver si me das un consejito sobre eso, te estaria muy agraecido… n_n
09-06-2009 at 17:36
Hola!
Un void es lo mismo que null, asi que debería ser un assertNull y el string podría ser un assertEqual. Aca te dejó un link a una documentación de SimpleTest http://rodrigoarce.com/simpletest-cheatsheet.html
Saludos
10-06-2009 at 12:28
Hola ALBO, y cuando hay una función que no devuelve nada, osea hay funciones en donde no terminan en ‘return’… un caso vendría a ser :
function api_session_register($variable) {
global $$variable;
session_register($variable);
$_SESSION[$variable] = $$variable;
}
en esta no veo que mande un return, que podria esperar yo aca, osea que tendria que retornar o que tendria que assert pondria aca…
ademas hay veces en donde el return no es un valor sino una cadena:
function api_store_result($result) {
$tab = array ();
while ($row = Database::fetch_array($result)) {
$tab[] = $row;
}
return $tab;
}
espero tu consejo, gracias
10-06-2009 at 19:22
Hola Ricardo, mira en cualquier caso lo que vos estas testeando es el comportamiento de una función o de un método asi que no importaría si devuelve o no algo. Tendrías tres casos (tanto para función como para método):
1. Devuelve algún valor
2. Tira alguna excepción
3. No devuelve nada
Para los casos 1 y 2 podes trabajar con el valor esperado y conociendo el comportamiento (al estilo caja negra, o sea sin saber que pasa por dentro) en cambio en el tercero, deberías conocer y trabajar con lo que modifica esa función, como el ejemplo que pusiste que modifica el $_SESSION. Ahi deberías hacer un assert para ver si el $_SESSION esta modificado como te corresponde.
En concreto:
$a = ‘value’;
api_session_register(’a');
$this->assertEqual($_SESSION[’a'], $a);
Saludos!
16-06-2009 at 11:12
Hola albo sabes me gustaria que me pudieras pasar un poco mas de informacion sobre el simpletest y algun truco que como experimentado (con mas conocimientos) me pudieras dar, tengo una pequeña presentacion sobre pruebas automatizadas usando simpletest y quisiera saber si me puedes guiar en algo mas.
TE LO AGRADECERÍA INFINITAMENTE.
Saludos
16-06-2009 at 12:06
Hola Ricardo, la verdad es que no tengo mas información. Lo único que te queda hacer es probar, probar y probar. No hay trucos, ni atajos. Probá hacer TDD, es la mejor manera de hacer tests efectivos y buen diseño y código.
Y en la presentación mostra todos los puntos buenos de UnitTest como las cosas se prueban una sola vez haciendo mas dificil introducir bugs en código de producción, mejora la interfaz, documenta el uso de las clases que se testean y hacen feliz al programador (cuando ves todos los tests en verdes te pones muy contento :D). Y sus puntos malos, como que llevan trabajo crearlos y mantenerlos y necesitan disciplina (muuuuuuuuucha pero muucha disciplina) por parte del equipo de desarrollo.
Saludos ;)
17-06-2009 at 13:02
gracias amigo ALBO, disculpa si me tomo la molestia de llamarte “amigo”, pero en verdad agradezco tu ayuda, me ha sido muy útil, también te agradezco el consejo. Espero poder llegar aprender más cosas, cualquier duda podre contar con tu ayuda?, espero que si.
atte.
Ricardo Rodriguez Salazar
_______________________
/ \
| —— Ing. de Sistemas —— |
\_______________________/
17-06-2009 at 16:38
Hola albo, mira tengo un problema al hacer mis pruebas, hago mis setUp( ) y mis tearDown( ) y aun asi me genera los datos en la base de datos… lo que me produce varios errores al momento de reinstalar mi sistema, dime que podria hacer para q eso no pase, ya que la funcion de mi setUp y mi tearDown es :
class TestBlog extends UnitTestCase{
public $oblog;
public function TestBlog(){
$this->UnitTestCase(’Blog Manipulation tests’);
}
public function setUp(){
$this-> oblog = new Blog();
}
public function tearDown(){
$this->oblog = null;
}
Esta bien eso o como puedo hacerlo ????
o que metodo realizo para poder hacer pruebas sin crearlo en la base de datos. ??
03-07-2009 at 12:24
Hola
Tengo un problema con una prueba export, ojala me puedan ayudar.
El codigo del metodo a probar es el siguiente:
function export_table_csv($data, $filename = ‘export’)
{
$file = api_get_path(SYS_ARCHIVE_PATH).uniqid(”).’.csv’;
$handle = @fopen($file, ‘a+’);
if(is_array($data))
{
foreach ($data as $index => $row)
{
$line=”;
if(is_array($row))
{
foreach($row as $value)
{
$line .= ‘”‘.str_replace(’”‘,’”"‘,$value).’”;’;
}
}
@fwrite($handle, $line.”\n”);
}
}
@fclose($handle);
DocumentManager :: file_send_for_download($file, true, $filename.’.csv’);
exit();
}
El problema es que cuando corro la prueba por navegador este me sale el titulo de la prueba pero lo demas esta en blanco. Ya eh tratado de colocar constructores y obejtos y nada (set up / tear down, ob_start() …). No se como podria realizar esta prueba.
Gracias de antemano. Saludos
03-07-2009 at 13:09
Hola albo, mira tengo un problemita, al momento de hacer pruebas con los contenedores ob_start() ob_get_contents() y eso, no me muestra el mensaje de pass o error en mi prueba, a menos que solo coloque la funcion $res = ob_get_contents() pero sin colocar de donde jala la funcion real…. te paso un ejemplo:
public function testCheckParameterOrFail(){
ob_start();
//$res = $this->tcourse->check_parameter_or_fail();
$res =ob_get_contents();
ob_end_clean();
//$this->assertTrue(is_string($res));
$this->assertFalse($res);
$this->assertFalse($res=== null);
//$this->assertEqual(null,$res);
}
si descomento las otras lineas, no me sale ninguna prueba, pero si dejo asi como esta, sale que pasa, solo que de esa manera, no estoy probando nada, que puedo hacer ?