Archive

Posts Tagged ‘simpletest’

A basic guide to unit testing, or how not to write unit tests

April 5, 2010 2 comments

Inside the bunch of implicit responsibilities I have in some projects, including the Chamilo project, one is to review the code of my fellow colleagues (or should I say team members).

The fact that we asked people with little experience in PHP programming to start writing automated tests was something of an experience, and it certainly proved… interesting. Most of these tests are simple. In fact they are down right basic. Most of these are also useful, even if basic, as they check some of the things that should never be broken (like the type of value a function returns).

I have had the first opportunity recently to check those tests, mostly concentrating on failing tests (which, by the way, are totally acceptable in non-previously tested code, as we will see below), and I must say I’ve had my share of surprises, even pulling tears out of my eyes on occasions. In short, some of these tests (around 2000 in total) really show why people writing unit tests *shoul be* experienced developers to start with.

First things first, let’s get a few basic things right

What is unit testing used for?

The first thing that might come to mind is this question. In fact, most people will just consider at first that testing would be much easier to be done by hand. Even initiated to the idea that automating tests will generate time savings, many developers being, by nature, lazy, will seriously reconsider it when faced when the additional task of learning how to setup automated tests, and then setting it up slowly.

Let’s not discuss test driven development here. This will come after developers already understand testing well enough.

But the fundamental interest of unit testing comes from regular control, when integrating it into continuous integration systems, for example. This ensures tests do not just tell you whether your current code runs right now, but rather if the latest version of your code broke something previously.

A few tips on how to write tests

Let’s not consider test suites, mock-ups, set up and tear down for now. What you need to know if that every test should be as independent of other tests as possible. As such, just testing a function should mean writing one *or more* test functions. For example, one to test the type of return value, and one to test the value returned for each combination of parameters. For example, trying to pass parameters should be done by testing a few extreme values (like sending null, string, negative, positive and zero values for integer types).

Let’s say you have a simple function that computes a special value from one integer. For the examples below, we are using the SimpleTest unit testing framework for PHP.

function compute_value($i) {
  return $i*$i+($i*2);
}

A simple set of tests would be:

function test_compute_value_zero_when_param_zero() {
  $res = compute_value(0);
  $this->assertIdentical($res,0);
}
function test_compute_value_false_when_param_string() {
  $res = compute_value('abc');
  $this->assertIdentical($res,false);
}
function test_compute_value_false_when_param_null() {
  $res = compute_value(null);
  $this->assertFalse($res);
}
function test_compute_value_int_when_param_int() {
  $res = compute_value(1);
  $this->assertTrue(is_int($res));
}

Let’s analyse these:

  • we defined several test functions, with distinct names for each one, covering only one function. In general, each parameter and combination thereof should be declined in all its possible values to make sure your function is rock-solid. Due to the impossibility to do that (there is possibly an infinity of possible values for each parameter), you use representative values that will help you sort out if your function reacts well to certain ranges.
  • we use asserts functions to check the return value (this comes with SimpleTest, you can find more about SimpleTest on LastCraft’s website)
  • some of the tests will probably fail (for example the null and string stuff), but that’s alright. In fact, it is very good to have tests fail. This shows that while testing, you thought of stupid things that you never thought could happen to your code, and now that you wrote tests about it, you will have to fix your code or else the tests won’t work

How to run the tests (using SimpleTest)

Now, very quickly because this isn’t the main idea of the article, if you want to run these tests, you’ll have to take the following steps. I’m assuming a series of things first:

  1. you downloaded the SimpleTest framework and put it into a ‘tests/simpletest/’ directory inside your project
  2. your function is inside a file called functions.lib.php under the directory ‘code/’
  3. your test code is inside a file called functions.lib.test.php under the directory ‘tests/’

Take the following steps:

  1. inside your functions.lib.test.php file, wrap your functions into a class that extends UnitTestCase (e.g.: class TestFunctions extends UnitTestCase { /*your functions here*/ })
  2. create a new file called “test.suite.php” inside the ‘tests/’ directory, and edit it
  3. require the SimpleTest libraries (something like require_once ‘simpletest/unit_tester.php’; require_once ‘simpletest/autorun.php’;)
  4. require the ‘code/functions.lib.php’ file (something like require_once ‘../code/functions.lib.php’;)
  5. declare a class, extension of the TestSuite class (something like:  class MySuite extends TestSuite {})
  6. inside the class, declare a constructor (function __construct() { })
  7. inside the constructor, load the test library ($this->addFile(‘functions.lib.test.php’);)
  8. outside the class, instantiate your test suite: $test = &new MySuite();

Now get out of all these files and load the test.suite.php script (either from your browser or from the command line)

What NOT to do

Now this is a short series of examples that you should try to avoid “commiting” inside any of your tests

if ($var == '') {
  $this->assertTrue(empty($var));
}

Obviously, given empty will return true when its parameter is an empty string, this assert will verify that the value is true… The thing is to never put a condition before an assert, that could alter the results. You are supposed to call your tested function in such a way that you know whether it should return an empty string or something else. If you are testing whether it returned an empty string, this means that you don’t understand what your function should return…

ob_start();
$res = compute_value(3);
$this->assertTrue(is_int($res));
ob_end_clean();

ob_start() and ob_end_clean() are used when you want to test whether a function returns the right value or not, but you don’t want your test to be showing all the strings that the function is outputting, so you hide it inside the output buffer and then you destroy it (you don’t care what it is, you just want the return value). Now, if you put the $this->assertTrue() call inside these two “markers”, the output of the $this->assertTrue() call will not appear on your screen, so you will know (from the global report) that there was an error, but you won’t know where it happened.

Note that displaying directly to the standard output from inside a function is a questionable technique in many cases.

// when $res is the result of a function returning
// either true or false, and we called it with
// a value that should return true...
$this->assertTrue(is_bool($res));

If you already expect your result to be true, test if it is true, not if it is a boolean!

if ($perm_dir != '0777') {
 $msg = "Error";
 $this->assertTrue(is_string($msg));
} else {
 //...
}

More obvious even… what you should check is the return value of the function checked. Assigning a constant value to a string and then testing whether it is a string is just… too useless to avoid laughing.

Conclusion

Although manual testing might be efficiently done by patient and observing people without development experience, unit testing is a whole different experience. You will probably need a full day training in order for your developers to understand how to do it. Don’t expect them to learn by doing it alone. Testing is a very complex process. Don’t assume testing is easier than writing the code. In fact, don’t assume anything. Try it, test it and see what’s happening.

Advertisements

Top projects of January 2010

February 12, 2010 Leave a comment

This year has taken a good start for us at BeezNest worldwide, and between writing around 3 times more offers than usually and launching new projects, we have been busy on a series of important missions that I’d like to take the opportunity to mention.

Gallery 2 and slow disk accesses

First of all, we’ve been busy trying to debunk a really well hidden flaw in an install of Gallery 2, whereby the “Comments” feature was so quickly getting spammed that the server could just not handle the number of requests sent by the application and a lot of other applications were slowing down.

Trees management

Second, we’ve been working a lot (in terms of development) on a system to manage… trees! What? Yes, trees (and green areas as well). You know, trees are like medical patients after all. Although they tend to fall less ill, there tends to be a whole lot of trees in our cities. Well, we’ve got one great system to do that, that we are working on with one of our partners. Thanks to the system, you can easily plan lifespans of the trees in a city or a larger entity, pinpoint them on a map, and make sure their illnesses and history is stored on something else than an easily lost/stolen/burnt piece of paper. Of course, you can assign tasks, classify trees by street or park, take photos, specify their height, level of danger, or protection put in place. It’s even compatible with Oracle Locator databases! Contact us if you’re looking for something like that.

Chamilo, a fresh e-learning project with experience

Ah well, we’ve decided to drop our support of the Dokeos platform and went on to create a fork, called Chamilo, which will defend a more open approach to e-learning platform development. At first, we thought we would need like half a year to get up and running with the project, but we’ve pretty much been overwhelmed by the overall surge of activity and the massive support and active contributions we’ve already received, while we haven’t setup the bank account for the association defending the project just yet. A great, positive sign for the first month of the project.

Flash stuff

We’ve also been working on a clothing application for a company selling custom t-shirts, whereby the visitor can try its own logos on the shirt he likes most. It was still not ready at the end of January, but we hope you’ll see it soon.

New support lines

We’ve started developing Spanish-based phone support services because a lot of our customers were asking for just that: a way to understand their problems fast and find a way to avoid them. Of course, we’ve also got a whole lot of development-type support coming out of that, but we’re just starting the first line support and it’s taking a good shape. If you are in need if this type of service, just call +51 1 719 51 92 and we’ll quickly deal the contract details with you before you can get access to our support.

Preparing international events

We’re going to be involved in two massive events this year: Expoelearning Lima, a huge e-learning event that will attract a hundred of e-learning companies from around Latinamerica; and the Software Freedom Day, also in Lima, to which we are planning to give a special taste of open knowledge by inviting a hugely famous (still secret) guest of the open knowledge area. We’ve also been dealing with all the graphical design aspect of these events, and our designer has been even more active during the end of January, but we’ll discuss this at the end of February.

Automated tests coverage

A considerable effort has been put into automating tests for Chamilo through SimpleTest, Phing and Xinc. We hope we’ll be able to show you the results very soon.

625 days uptime

We’re always informing our customers that a Linux server that we take time to configure can cut down on future management expenses considerably. One of our customers has just had one of its servers reach 620 days uptime at the end of January. This means the server has been working for almost 2 years (we’ll reach that point in a few months time) without reboot of any kind. This server is used as a web server and has only required a few updates during the last 2 years. This effectively means that this in-house server maintenance costs were brought down to a minimum, while continuing to server its visitors reliably.

Contributing to FLOSS

As usual, the Peruvian offices (Lima, Miraflores) has been hosting meetings from the Python Perú and Drupal Perú groups, and will be hosting additional PHP and Chamilo meetings in March. Of course, we’ve continued working on key open-source projects like Chamilo and OpenC2C

Categories: English, News Tags: , , , , ,

Reunión conjunta PHP Perú y Drupal Perú, este Sábado 12/12/2009

December 10, 2009 Leave a comment

Este Sábado 12/12 a las 3pm, las comunidades de PHP Perú y Drupal Perú se reunirán en nuestras oficinas para hablar de Xapian, SimpleTest y el tema Elements de Drupal 6.

Más info en http://groups.drupal.org/node/35790

En la mañana, estaremos en el evento de Unacinux en el Callao: http://csl.unac.edu.pe/cronograma.php, para hablar de software libre exitoso en la educación peruana (Drupal, OpenERP, KnowledgeTree, PMB, OpenC2C, …)

Categories: eventos, Spanish Tags: , , ,

phpUnderControl, PHP_CodeSniffer and PHPUnit

Just a quick link to a few sites that I want to remember in a few days time, when I’ll try to get more information about the differences between PHPUnit and SimpleTest.

http://phpundercontrol.org/about.html

http://pear.php.net/package/PHP_CodeSniffer

http://maphpia.com/impacto-estimable-gracias-a-unit-testing/ (in Spanish)

Instalar Phing y Xinc en Ubuntu

Este proceso de instalación es específico a Ubuntu 9.10. Puede que funcione con otros sistemas operativos o otras versiones, pero solo estamos seguros para esta configuración.

Instalar SimpleTest

Phing necesitará SimpleTest. En el paquete de Chamilo, SimpleTest está disponible como una carpeta con una de las últimas versiones de SimpleTest. Para evitar problemas luego con la versión instalada por el sistema es mejor de instalar la versión que está en Chamilo a nivel del sistema. Hay varias soluciones para hacerlo, de las cuales posiblemente la más limpia es de agregar la carpeta tests/simpletest de Chamilo en el include_path de la config de PHP. Si no quiere tomar el tiempo de hacerlo, en una Ubuntu, puede hacer un sudo apt-get install php-simpletest y después sobreescribir los ficheros en /usr/share/php/simpletest/ con los de Chamilo (es malo, lo sé, pero asumo que la máquina en la cual se hace la instalación es una máquina de desarrollo por ahora).

Instalar Phing

$ sudo pear channel-discover pear.phing.info
$ sudo pear install phing/phing

A este punto, prueba de ejecutar “phing” en la línea de comando. Si el sistema no encuentra el comando, prueba ejecutar el script de configuración de Phing

$ sudo pear run-scripts phing/phing

Esto debería crear un /var/www/phing dentro del cual se puede editar el build.xml para customisarlo. Un ejemplo de build.xml

<?xml version="1.0"?>
<project name="chamilo187" default="clean" basedir=".">
 <target name="empty">
  <echo msg="Cleaning working space..." />
  <delete file="chamilo*.tgz" />
 </target>
 <target name="prepare" depends="empty">
  <echo msg="Preparing build..." />
  <mkdir dir="./chamilo-1.8.7" />
 </target>
 <target name="copy" depends="prepare">
  <echo>Copying...</echo>
  <copy todir="./chamilo-1.8.7/">
   <fileset dir="/var/www/chamilohg">
    <exclude name="**/.svn" />
   </fileset>
  </copy>
  <delete file="**/.svn" />
 </target>
 <target name="syntax-check" depends="copy">
  <phplint>
   <fileset dir="./chamilo-1.8.7">
    <include name="**/*.php"/>
   </fileset>
  </phplint>
  <simpletest printsummary="true">
  <formatter todir="reports" type="plain" />
   <fileset dir="./chamilo-1.8.7/tests">
    <include name="dummy.test.php" />
   </fileset>
  </simpletest>
 </target>
 <target name="documentation" depends="syntax-check">
  <phpdoc title="Chamilo API" destdir="doc" output="HTML:Smarty:PHP">
   <fileset dir="./chamilo-1.8.7">
    <include name="**/*.php" />
   </fileset>
  </phpdoc>
 </target>
 <target name="dist" depends="documentation">
  <echo message="Creating archive..." />
  <tar destfile="chamilo-1.8.7.tgz" compression="gzip">
   <fileset dir="./chamilo-1.8.7">
    <exclude name="**/*.bak" />
   </fileset>
  </tar>
 </target>
 <target name="clean" depends="dist">
  <echo msg="Cleaning up..." />
  <delete dir="./chamilo-1.8.7" includeemptydirs="true" verbose="true" failonerror="true" />
 </target>
</project>

Una vez el proyecto Phing listo (dentro del build.xml), basta lanzar, en línea de comando, un “phing” para iniciar el proceso.

Phing executing in a terminal

Phing executing in a terminal

La documentación (en Inglés) de Phing esta disponible acá: http://phing.info/docs/guide/2.2.0/

Instalar Xinc

Xinc's first screen

Xinc's first screen

$ sudo pear channel-discover pear.xinc.eu
$ sudo pear install xinc/Xinc

El último comando ejecuta montones de cosas.

Según los resultados, es posible que sea necesario ejecutar una serie de comandos adicionales como:

$ sudo pear install channel://pear.xinc.eu/Xinc-2.0.0b196
$ sudo pear install channel://pear.php.net/VersionControl_SVN-0.3.3
$ sudo pear channel-discover components.ez.no
$ sudo pear install channel://components.ez.no/Base
$ sudo pear install channel://components.ez.no/Graph
$ sudo apt-get install php5-xsl

Posiblemente, este paso falla, pero en el mensaje de error aparece el URL que debería cargar en sitio de “xinc/Xinc” en el último comando.

Después de instalar, es necesario ejecutar el comando

$ sudo pear run-scripts xinc/Xinc

Lamentablemente, si ha tenido que usar el URL en lugar de xinc/Xinc, podría ser necesario cambiar este último comando también (algo como pear.xinc.eu/Xinc). Este comando debería retornar algo parecido a esto:

Including external post-installation script "/usr/share/php/Xinc/Postinstall/Nix.php" - any errors are in this script
Inclusion succeeded
running post-install script "Xinc_Postinstall_Nix_postinstall->init()"
init succeeded
 1. Directory to keep the Xinc config files                    : /etc/xinc
 2. Directory to keep the Xinc Projects and Status information : /var/xinc
 3. Directory to keep the Xinc log files                       : /var/log
 4. Directory to install the Xinc start/stop daemon            : /etc/init.d
 5. Directory for xinc`s temporary files                       : /tmp/xinc
 6. Do you want to install the SimpleProject example           : yes
 7. Directory to install the Xinc web-application              : /var/www/xinc
 8. IP of Xinc web-application                                 : 127.0.0.1
 9. Port of Xinc web-application                               : 8080

1-9, 'all', 'abort', or Enter to continue:
Successfully copied /usr/share/php/data/Xinc/xinc.ini.tpl  to: /usr/share/php/data/Xinc/xinc.ini
Successfully copied /usr/share/php/data/Xinc/etc/xinc/*  to: /etc/xinc
Successfully copied /usr/share/php/data/Xinc/examples/SimpleProject  to: /var/xinc/projects
Successfully copied /usr/share/php/data/Xinc/web/.htaccess  to: /var/www/xinc
Successfully copied /usr/share/php/data/Xinc/web/*  to: /var/www/xinc
Successfully copied /usr/share/php/data/Xinc/scripts/xinc-uninstall  to: /usr/bin/xinc-uninstall
Successfully copied /usr/share/php/data/Xinc/scripts/xinc-uninstall.php  to: /usr/bin/xinc-uninstall.php
Xinc installation complete.
- Please include /etc/xinc/www.conf in your apache virtual hosts.
- Please enable mod-rewrite.
- To add projects to Xinc, copy the project xml to /etc/xinc/conf.d
- To start xinc execute: sudo /etc/init.d/xinc start
UNINSTALL instructions:
- pear uninstall xinc/Xinc
- run: /usr/bin/xinc-uninstall to cleanup installed files
[OK] Saved ini settings
Install scripts complete

En este momento, es importante entender que Xinc debe ser el que maneja la actualización desde el repositorio de gestión de versiones. La razón es que xinc se va a encargar de la parte “integración contínua”. Si Xinc no puede manejar el mismo la actualización de mi código, como se va a dar cuenta si hubó un cambio? No puede! Entonces tiene el mismo que poder encontrar los cambios de versiones y darse cuenta si hubó un cambio. Esto implica sacar la parte de actualización automática del Phing, y dejarlo a Xinc.

Al fin de la instalación, es necesario reconfigurar y pasar el virtual host ubicado en /etc/xinc/www.conf dentro de /etc/apache2/sites-available/ y activarlo con

$ sudo cp /etc/xinc/www.conf /etc/apache2/sites-available/xinc.host.ext
$ sudo a2ensite xinc.host.ext
$ sudo /etc/init.d/apache2 reload

Para tener un resultado interesante en Xinc, es necesario tener unos scripts de prueba en SimpleTest o PHPUnit, y Phing instalado (más sobre las pruebas más tarde).

Antes de iniciar Xinc, es necesario configurar un proyecto. En nuestro caso, estaremos montando un proyecto llamado “chamilo” con un repositorio Mercurial en https://sources.beeznest.net/public/chamilo/

$ sudo mkdir -p /var/xinc/projects/chamilo
$ cd /var/xinc/projects/chamilo/
$ sudo hg clone https://sources.beeznest.net/public/chamilo/

Esto descargará la última versión de desarrollo de Chamilo.

Ahora el nuevo problema es que Xinc no soporta Mercurial… Una solución podría ser de ejecutar las cosas relativas a Mercurial en línea de comando desde la tarea Phing, pero lamentablemente Xinc necesita una visibilidad sobre las revisiones de Mercurial para poder devolver resultados interesantes. Por esto hemos desarrollado una versión básica del módulo de Hg para Xinc, que puede pedirnos por correo (no lo ponemos en línea todavía porque no está estable y no queremos que se moleste si le rompe su proyecto).

Configurar el proyecto Xinc

La configuración de Xinc en sí se hace dentro de /etc/xinc/conf.d, donde se encuentra un fichero simpleproject.xml que se puede modificar. Sino quiere tener un proyecto “simpleproject” fantasma, entonces mejor mover este fichero de otro lado y hacer una copia ahí, renombrar el archivo y editar sus detalles *antes* de iniciar Xinc por primera vez (después es bastante complicado de quitar este proyecto fantasma).

Por ejemplo, renombramos el archivo simpleproject.xml en chamilo.xml y le damos el contenido siguiente.

<?xml version="1.0"?>
<xinc engine="Sunrise">
 <project name="chamilo">
 <configuration>
 <setting name="loglevel" value="1"/>
 <setting name="timezone" value="America/Lima"/>
 </configuration>
 <property name="dir" value="${projectdir}/${project.name}"/>
 <schedule interval="3600" />
 <!--cron timer="* */2 * * *"/-->
 <modificationset>
 <hg directory="${dir}/chamilo/" update="true" />
 <!--buildalways/-->
 </modificationset>
 <builders>
 <phingBuilder buildfile="${dir}/build.xml" target="build"/>
 </builders>
 <publishers>
 <simpleTestTestResults file="${dir}/reports/testresults.txt"/>
 <onfailure>
 <email to="ywarnier@beeznest.org"
 subject="${project.name} build ${build.number} failed"
 message="The build failed."/>
 </onfailure>
 <onsuccess>
 </onsuccess>
 <onrecovery>
 <email to="ywarnier@beeznest.org"
 subject="${project.name} build ${build.number} was recovered"
 message="The build passed after having failed before."/>
 </onrecovery>
 </publishers>
 </project>
</xinc>

Analizemos un poco:

<project name="chamilo">

-> el proyecto se llama “chamilo”. Esto también define la variable ${project.name}

<schedule interval="3600" />

-> la actualización corre cada 3600 segundos

<hg directory="${dir}/chamilo/" update="true" />

-> definimos que la fuente del proyecto (hg=mercurial) se encuentra en ${dir} (definido antes), subcarpeta /chamilo/. Desde ahí, y con las tareas Xinc definidas,

<phingBuilder buildfile="${dir}/build.xml" target="build"/>

-> define donde encontrar el archivo de construcción del proyecto (construcción que se hace con Phing)

 <simpleTestTestResults file="${dir}/reports/testresults.txt"/>

-> define donde encontrar el archivo de reporte de las pruebas. Una vez más, faltaba integración para SimpleTest aquí, así que desarrollamos los scripts a partir de los de PHPUnit. Ver http://code.google.com/p/xinc/issues/detail?id=206

Lo demás define como generar reportes en caso de éxito, de falla o de recuperación. En caso de éxito, se podría definir que se ejecuta otro proyecto Phing, que sirve para la construcción del paquete (como por ejemplo hacer un archivo Zip, en la forma de un fichero de configuración Phing package.xml por ejemplo).

Por el hecho de tener el control de versiones hecho a nivel de xinc, podemos tener un build.xml de Phing muy reducido:

<?xml version="1.0"?>
<project name="chamilo" default="build" basedir=".">
 <property name="builddir" value="chamilo/" override="true" />

 <target name="order">
   <echo msg="Copying cli_install..." />
   <copy file="cli_install.php" tofile="./${builddir}main/install/cli_install.php" overwrite="true"/>
   <echo msg="Moving local simpletest copy to avoid using it (use system's library)..." />
   <move file="${builddir}tests/simpletest" todir="${builddir}tests/simpletestbak" includeemptydirs="true" />
 </target>

 <target name="install" depends="order">
   <echo msg="Installing Chamilo..." />
   <exec command="chmod -R 0777 *" dir="${builddir}" />
   <echo msg="Assigned development permissions..." />      
   <exec command="php5 cli_install.php -l admin -p admin -U chamilo -P chamilo -u 'http://phing.chamilo.net' -X 'chamilophing_'" dir="./${builddir}main/install/" />
   <echo msg="Hopefully installed..." />      
 </target>

 <target name="simple-tests" depends="install">
   <echo msg="Starting tests..." />
   <simpletest>
     <formatter todir="reports" type="plain"/>
     <fileset dir="${builddir}tests">
       <include name="all.test3.php" />
     </fileset>
   </simpletest>
 </target>

 <target name="build" depends="simple-tests">
   <echo msg="Cleaning up the database..." />
   <exec command="php5 cleandb.php" dir="." />
   <echo msg="Moving back local simpletest copy..." />
   <move file="${builddir}tests/simpletestbak" todir="${builddir}tests/simpletest" includeemptydirs="true" />
   <echo msg="All clean!" />
 </target>
</project>

Esta combinación de los proyectos Phing y Xinc implica que tenemos que tener una carpeta /var/xinc/projects/chamilo que contenga

  • un repositorio Mercurial de nuestro Chamilo (checkeado con el usuario root para poder hacer la actualización después via Xinc)
  • un script cli_install.php que instale un Chamilo en línea de comando
  • un script cleandb.php que limpie la base de datos después de las pruebas

Si ocurre un error en la construcción, probar de ver los logs de xinc así

$ sudo tail -f /var/log/xinc.log

Si ocurre un error en la construcción del paquete, es posible que tenga más detalles un archivo de log en /var/xinc/projects/chamilo/

Para iniciar Xinc

$ sudo /etc/init.d/xinc start

La documentación (en Inglés) de Xinc esta disponible acá: http://www.xinc.eu/api/documentation/get/file/xinc/latest-successful/Enduser/index.html

Cuando empieza a correr el Xinc, en general (si ha instalado como indicado arriba) en la version 2.0.0 tiene un problema para jalar la buena libreria para generar los graficos. Esto se puede arreglar editando un archivo de Xinc (como indicado en http://code.google.com/p/xinc/issues/detail?id=167):

sudo vim /usr/share/php/Xinc/Plugin/Repos/Gui/Statistics/Graph.php

y ahí, editar la línea 33 (después de un comentario vacío) para agregar

require 'ezc/Base/ezc_bootstrap.php';

y después reiniciar a Xinc con

/etc/init.d/xinc restart

Para parar Xinc

$ sudo /etc/init.d/xinc stop

Instalar el plugin SimpleTest para Eclipse

January 4, 2009 1 comment

Por si a caso usted quiere hacer pruebas con SimpleTest (un framework para pruebas unitarias en PHP) y tiene Eclipse 3.2 instalado, una manera simple de probarlo es de instalar el plug-in SimpleTest para Eclipse. Este articulo prueba de simplificarle la tarea, y esta basado en la página en Inglés: http://simpletest.org/en/extension_eclipse.html

Tengo entendido que el aporte mayor de SimpleTest en comparación con PHPUnit (o PHPUnit2) es que se puede usar un “navegador virtual” que permite de hacer pruebas directamente con resultados HTML de escripts PHP. Un poco (pero no enteramente) como lo hace ahora Selenium IDE, dentro de Firefox, pero en este caso no necesitamos un navegador, lo que facilita considerablemente las pruebas automatisadas de interfaz.

Primero, se tiene que seguir, dentro de Eclipse, los menus Help > Software Updates… y seleccionar la pestaña Available Software.

Como usted seguro no habrá probado anteriormente de instalarlo, tiene que agregar un site de descarga del plugin. Haz click por el botón Add Site… y entra como URL http://www.simpletest.org/eclipse/ y valide.

Esto brinda el URL http://www.simpletest.org/eclipse/ en la lista a la izquierda. Seleccionelo y se abre, ofreciendo una categoría Uncategorized. Seleccione esta categoría y en particular el Simpletest plug-in que hay a dentro, y haz click por Install…

Después de confirmaciones de licencia (es la licencia Eclipse que se accepta para el plug-in, no para el SimpleTest (que es bajo licencia LGPL), el sistema les pide para reiniciar Eclipse. No se lo que occurre cuando no se reinicia pero tengo entendido que no es recomendable.

Reinicia el sistema y… no aparece nada nuevo! Por supuesto, el SimpleTest plug-in es un plug-in chiquito, y no hace mucho, pero ante todo se tiene que configurar. Para esto, vamos a Window > Preferences > SimpleTest y configuramos los 3 elementos necesarios: Php.exe file (que bajo un sistema Ubuntu será /usr/bin/php si usted ha instalado el paquete php5-cli), php.ini file (que será, bajo el mismo sistema, /etc/php5/cli/php.ini) y Test File Suffix (que será simplemente .php pero podría ser .test.php si todos sus tests están con esta extensión). Los demás parámetros no son necesarios.

Apunte que el SimpleTest plug-in en realidad instala el SimpleTest entero, y lo instala en una carpeta de Eclipse y agrega, en el contexto de Eclipse, esta librería dentro del include path. Esto quiere decir que si pruebo de cargar SimpleTest dentro de mis escripts de test, no va a funcionar (doble declaración). Lo vemos mas allá.

Ahora que tengo configurado mi plug-in, que puedo hacer? Pues no mucho. Lo único que puedo hacer es hacer click derecho por algún script que tengo y decir Run as… > SimpleTest. Y esto lanzará mi escript de test incluyendo la librería SimpleTest por defecto. Lo interesante ahí es que el output de esta prueba aparece directamente en una nueva zona de Eclipse que se dedica a eso.

Por ejemplo, quiero empezar a crear pruebas simples para Dokeos. Donde inicio mi trabajo?

Pues la lógica primera de SimpleTest y PHPUnit incita a tener una carpeta aparte que se llame tests y dentro de cual voy a tener todas mis pruebas, con un fichero (una clase) diferente para cada tipo de prueba. Una clase de pruebas podrá probar muchas cosas, pero se considera que una clase debería tener solo la prueba de una funcionalidad (sea una funcionalidad simple pero importante, o otra mucho más compleja que incluye otras, pero nunca dos pruebas que no tienen nada que ver dentro de una sola clase).

Usando Eclipse, creo una carpeta tests dentro de la cual creo mi primer fichero: dummy.test.php

<?php
//require_once(‘simpletest/autorun.php’);

class TestDummy extends UnitTestCase
{
function testDummyValues()
{
$this->assertFalse(false);
$this->assertTrue(false);
}
}
?>

He tomado un ejemplo muy básico aquí, que no tiene nada que ver con Dokeos. Usted se dará cuenta que tengo un require_once comentado en primera línea. Esto es lo que le comentaba más arriba, de que Eclipse ya incluye la librería SimpleTest, por eso no se tiene que incluir más.

Después declaro una clase que extende la clase UnitTestCase (hay otras clases de base que extender, por ejemplo para pruebas navegador) y un método testDummyValues() que va a hacer las pruebas realmente.

Ahora, esto es mi prueba básica. Para ver como se comporta SimpleTest, lo único que me falta es hacer click-derecho por el script y Run as > SimpleTest y… ya tengo mi salida (como ustedes se imaginarán mirando al ejemplo, la primera prueba resulta bien, la segunda no:

Salida de SimpleTest plug-in en Eclipse

Salida de SimpleTest plug-in en Eclipse

Me retorna el número de fallas de mis pruebas, así que el número de errores generadas, y me indica donde ha occurrido este error.

A cambio, si todo funciona, me sale esto (yo he desplegado los detalles pero sino solo indica el nombre del fichero de la prueba):

SimpleTest output on success

SimpleTest output on success

Ya esta para esta vez. Mas allá probablamente explicaré como hacer una prueba de funcionalidad con Dokeos…

Puede seguir la guía simple en Inglés de inicio con SimpleTest aquí, pero se supone que conoce las bases de unit testing con PHP…

%d bloggers like this: