Title: BUnit.h: Un m
1BUnit.hUn módulo C simple para aprender
prueba unitaria de programas
- Universidad de Costa Rica
- Escuela de Ciencias de la Computación e
Informática - Prof. Adolfo Di Mare
- adolfo.dimare_at_ecci.ucr.ac.cr
2Agenda de Trabajo
- Motivación
- Doxygen es parte de la solución
- Formar a los jóvenes para convencer a los viejos
- Probar y especificar antes de codificar
- Arquitectura de BUnit
- Especificación por medio de prueba de programas
- Formato de la documentación Doxygen
- Experiencia con estudiantes
- Detalles de implementación
- Posibilidades de ampliación
- Conclusiones
- Código fuente
3Programación II
- Módulos
- Especificación
- Reutilización
4Doxygen
- Dimitri van Heesch
- http//www.doxygen.org
- Es necesario inculcar en los programadores la
disciplina de especificar antes de programar, o
sea, de diseñar antes de construir, para mejorar
la calidad del producto final.
5Motivación
- Así como las bailarinas son felices cuando
danzan, los programadores obtienen su
gratificación cuando programan. - BUnit.h permite usar datos de prueba como
ejemplos que complementan la especificación de un
módulo.
6Motivación
- Construir la especificación antes de la
implementación. - Incorporar los datos de prueba como parte de la
especificación de cualquier módulo.
7De los Jóvenes a los Viejos
- Es difícil convencer a los profesores
- Es difícil convencer a los jefes
- Es más fácil lograr que los jóvenes adopten
prácticas mejores de trabajo - Los resultados convencen a los viejos
8Especificación, Prueba, Codificación
- Quien no sabe adónde vá... llega a otro
lado! - Agregue una prueba, hágala fallar, codifique el
algoritmo para pasar la prueba y por último
elimine la redundancia - Escriba una prueba en cada ocasión en que se vea
tentado a usar una instrucción "print()"
9Arquitectura de Bunit.h
- ----------------
- TestCase
- ----------------
- run() 0
- successCount()
- failureCount()
- assertTrue()
- ----------------
- Fixture
- - setUp()
- - tearDown()
- ----------------
- /\
-
- -------------------------
- TestSuitelt TestCase gt
- -------------------------
- addTest ( TestCase )
- addSuite( TestSuite )
10include "BUnit.h" // 1 Agregrar include
"BUnit.h" /// Ejemplo mínimo de uso de \c
BUnit. class test0 public TestCase // 2
Derivar de TestCase public bool run()
assertTrue( 1 1 3 ) // 3 Invocar
assertTrue() return wasSuccessful()
include ltiostreamgt // stdcout ///
Programa principal que ejecuta la prueba. int
main() test0 test0_instance
test0_instance.run() // 4 run() Ejecutar las
pruebas if ( ! test0_instance.wasSuccessful()
) stdcout ltlt test0_instance.report()
return 0
11Determina si existe un camino en el grafo
comenzando en "src" y terminando en "dst". Si src
dst retorna "true" (un vértice siempre está
conectado consigo mismo). Retorna "true" cuando
el camino existe, y "false" en caso contrario. La
lista "C" contiene la secuencia de nodos del
camino. Si no hay camino, la lista "C" queda
vacía.
bool Graphconnected( const stdstring
src, const stdstring dst, stdlistlt
stdstring gt C ) // testdiagram()
A(1) C(1) O(1)----gtO(2) / \
/ \ /\ / \ /
\ F-gt--A(2)--gt-B-gt
-gtD \ / \ /
\ / \ /
\/ A(3) C(2)
O(4)lt----O(3) // testconnected()
assertTrue( G.connected( "F" , "F", C ) )
// si está conectado assertTrue( C.size()
1 C.front() "F" ) // porque ya está ahí
assertTrue( ! G.connected( "???" , "???", C )
) // no existe el vértice assertTrue( !
G.connected( "F" , "O(4)", C ) ) // grafo no
conexo assertTrue( C.size() 0)
assertTrue( ! G.connected( "D" , "F" , C ) )
// el grafo es dirigido assertTrue( C.size()
0)
12 // testdiagram() A(1) C(1)
O(1)----gtO(2) / \ / \ /\
/ \ / \
F-gt--A(2)--gt-B-gt -gtD \
/ \ / \ /
\ / \/ A(3)
C(2) O(4)lt----O(3)
// testconnected() stdlistlt
stdstring gt C // camino en el grafo
stdlistlt stdstring gtiterator it
assertTrue( ! G.connected( "???" , "???", C ) )
// no existe el vértice assertTrue( !
G.connected( "F" , "O(4)", C ) ) // grafo no
conexo assertTrue( C.size() 0)
assertTrue( ! G.connected( "D" , "F" , C ) )
// el grafo es dirigido assertTrue( C.size()
0) assertTrue( G.connected( "F" , "F", C
) ) // si está conectado assertTrue(
C.size() 1 C.front() "F" ) // porque ya
está ahí assertTrue( ! G.connected( "D",
"A(2)" , C ) ) assertTrue( C.size() 0 )
assertTrue( G.connected( "A(2)" , "D", C ) )
assertTrue( C.size() 4 ) assertTrue(
C.front() "A(2)" C.back() "D" ) it
C.begin() it assertTrue( it "B" )
// 2do nodo en el camino it
assertTrue( it "C(1)" it "C(2)" ) //
3er nodo en el camino
13Documentación Doxygen
/ Determina si existe un camino en el grafo
comenzando en \c "src" y terminando en \c
"dst". - Si ltcodegt src dst lt/codegt retorna
\c "true" (un vértice siempre está
conectado consigo mismo). - Retorna \c "true"
cuando el camino existe, y \c "false" en
caso contrario. - La lista \c "C" contiene la
secuencia de nodos del camino. - Si no hay
camino, la lista \c "C" queda vacía.
\dontinclude test_Graph.cpp \skipline
testdiagram() \until \skipline
testconnected() \until \see
test_Graphtest_connected() / bool
Graphconnected( const stdstring src ,
const stdstring dst , stdlistlt
stdstring gt C ) // ... implementación
14Datos de prueba BUnit
/// Datos de prueba para los constructores de la
clase \c TestCase. void test_BUnittest_construct
or() // testconstructor()
test_BUnit thisTest assertTrue(
stringnpos ! thisTest.getName().find(
"test_BUnit" ) ) assertTrue(
thisTest.failureCount() 0 )
assertTrue( thisTest.countTestCases() 1 )
assertTrue( thisTest.successCount() 0 )
assertTrue( thisTest.runCount() 0 )
assertTrue( thisTest.failureString() ""
) // Resto de las pruebas
test_BUnit thisTest assertTrue(
thisTest.m_pass 0 ) assertTrue(
thisTest.m_failure 0 ) assertTrue(
thisTest.m_name 0 ) assertTrue(
thisTest.m_failureList.empty() )
15Experiencia con estudiantes
- BUnit es fácil de usar
- No se percatan de que están usando una
herramienta - Se acostumbran a una mejor calidad en la
documentación - Hacer las pruebas BUnit es otra forma de
programación - Incorporan DoxygenBUnit en su práctica diaria
- Luego aprenden los conceptos relevantes
- Abstracción, Especificación, Prueba Unitaria, etc.
16Implementación
- assertTrue() está implementado como una macro C
- Se usan las macros predefinidas del compilador
__LINE__ y __FILE__ - Se registran en una lista las pruebas que no
tienen éxito
17Posibilidades de Ampliación
- Clase TestResult
- Clase TestFixture
- Mayor compatibilidad con JUnit
- Barra de progreso
- Extensión a JavaJavaDoc
18Conclusiones
- BUnit.h es simple cabe en un solo archivo de
encabezado. - BUnit.h es compatible con herramientas de la
familia JUnit. - La pareja BUnit.hDoxygen permite mejorar la
calidad de la especificaciones de módulos
19Código fuente
- http//www.di-mare.com/adolfo/p/BUnit/BUnit.zip
- http//www.di-mare.com/adolfo/p/BUnit/es/
- http//www.di-mare.com/adolfo/p/BUnit/en/
Muchas gracias