Author: tziade
Date: Fri Mar 10 18:05:25 2006
New Revision: 2571

Added:
   cookbook/trunk/recipe48.fr.tex
   cookbook/trunk/recipe49.fr.tex
   cookbook/trunk/recipe50.fr.tex
   cookbook/trunk/recipe51.fr.tex
   cookbook/trunk/tests.txt   (contents, props changed)
   cookbook/trunk/textest.py   (contents, props changed)
Modified:
   cookbook/trunk/macros.tex
   cookbook/trunk/recipe7.fr.tex
   cookbook/trunk/recipe_list.txt
   cookbook/trunk/tests.py
Log:
save point 'veauville' commit, before i forget

Modified: cookbook/trunk/macros.tex
==============================================================================
--- cookbook/trunk/macros.tex   (original)
+++ cookbook/trunk/macros.tex   Fri Mar 10 18:05:25 2006
@@ -12,8 +12,10 @@
 
 \newenvironment{problem}
 {
+\emph{\large{Probl�me}}
+\begin{quote}
 }
-{}
+{\end{quote}}
 
 \newenvironment{solution}
 {
@@ -25,3 +27,28 @@
 
 \newcommand{\translator}[1]{
 }
+
+\newcommand{\reviewer}[1]{
+}
+
+
+\newcommand{\code}[1]{
+\url{#1}
+}
+
+\newcommand{\codetitle}[1] {
+\vspace{4pt}
+\noindent\emph{\underline{#1}}
+}
+
+\newenvironment{codenotes}
+{\hrule
+\begin{list}{$\triangleright$}{\setlength{\leftmargin}{1em}}
+}
+{\end{list}}
+
+\newcommand{\comment}[1]{
+\begin{comment}
+#1
+\end{comment}
+}

Added: cookbook/trunk/recipe48.fr.tex
==============================================================================
--- (empty file)
+++ cookbook/trunk/recipe48.fr.tex      Fri Mar 10 18:05:25 2006
@@ -0,0 +1,105 @@
+\documentclass{book}
+\pagestyle{headings}
+\include{macros}
+\status{draft}
+\author{Tarek Ziad�}
+
+\begin{document}
+
+\chapter*{Ecrire du reSTructuredText pour la documentation et les doctests}
+
+\begin{problem}
+L'ensemble de la documentation des paquets de Zope est r�alis�e au format
+reSTructuredText, ou reST, qui est une �volution du StructuredText. Ce format
+fourni une structure simple, qui n'alourdit pas le texte, contrairement �
+LaTeX, et peut �tre lu directement. Des outils permettent ensuite de manipuler
+ce contenu pour le transformer en HTML, LaTeX, XML ou PDF.
+
+Cette recette est une \textit{cheatsheet} minimale, qui permet d'�crire des
+doctests destin�s � des paquets Zope.
+\end{problem}
+
+\begin{solution}
+\section*{Structurer le fichier}
+Pour organiser un fichier en section, sous-section, sous-sous-section, etc.,
+il suffit de souligner le titre de la section avec un caract�re dans 
l'ensemble:
+\code{\/-=} ** a v�rifier **. A chaque section, si un nouveau caract�re est
+utilis�, reST l'associe au niveau donn� pour le reste du document.
+
+\codetitle{Exemple de structure reST:}
+\begin{verbatim}
+Titre
+=====
+
+Ok, donc j'ai deux sections. Profitez-en.
+
+Section 1
+~~~~~~~~~
+
+Le titre est un frimeur. j'en parle dans une sous-section.
+
+Sous-Section 1
+--------------
+
+Je suis charg� par ma section de casser du sucre sur le dos
+de Titre, mais je n'en ferais rien, je vise une promotion.
+
+Section 2
+~~~~~~~~~
+
+Calmons nous, le document est fini de toute mani�re...
+\end{verbatim}
+
+\section*{Ins�rer des exemples de code}
+
+Ins�rer du code se fait en l'indentant d'au minimum 1 caract�re (en g�n�ral 2
+ou 4). Ce bloc doit �tre pr�c�d� du signe "::" et d'une ligne vide, puis
+suivi d'une ligne vide.
+
+\codetitle{Insertion de code:}
+\begin{verbatim}
+Le module Math
+==============
+
+Python dispose d'un module math, qui fourni une fonction pour les puissances::
+
+  >>> import math
+  >>> math.pow(56, 3)
+  175616.0
+
+Il y a aussi pi::
+
+  >>> math.pi
+  3.1415926535897931
+\end{verbatim}
+\begin{codenotes}
+\item Zope 3 indente de deux caract�res, mais certains d�veloppeurs pr�f�rent
+une indentation sur 4 caract�res, peut �tre pour �diter plus facilement
+ces fichiers dans leur �diteur de code Python.
+\end{codenotes}
+
+\section*{Ins�rer des liens et formatter le texte}
+
+\noindent reST permet aussi d'afficher du texte en italique, en gras.
+
+\codetitle{Gras et italique:}
+\begin{verbatim}
+Recette
+=======
+
+Il n'y a absolument pas de **gras** dans les plats `italiens`.
+\end{verbatim}
+
+\noindent La notation italique est utilis�e pour mettre en exergue un module
+ou tout �l�ment de code dans le texte. La notation grasse est r�serv�e � la
+mise en valeur de mots du texte.
+
+Pour les liens, AFINIR
+
+\section*{Bonnes pratiques en vrac}
+
+AFINIR
+
+\end{solution}
+
+\end{document}

Added: cookbook/trunk/recipe49.fr.tex
==============================================================================
--- (empty file)
+++ cookbook/trunk/recipe49.fr.tex      Fri Mar 10 18:05:25 2006
@@ -0,0 +1,21 @@
+\documentclass{book}
+\pagestyle{headings}
+\include{macros}
+\status{draft}
+\author{Tarek Ziad�}
+
+\begin{document}
+
+\chapter*{Utiliser zapi dans les tests}
+
+\begin{problem}
+TODO
+\end{problem}
+
+\begin{solution}
+TODO
+\end{solution}
+
+\end{document}
+
+

Added: cookbook/trunk/recipe50.fr.tex
==============================================================================
--- (empty file)
+++ cookbook/trunk/recipe50.fr.tex      Fri Mar 10 18:05:25 2006
@@ -0,0 +1,172 @@
+\documentclass{book}
+\pagestyle{headings}
+\include{macros}
+\status{draft}
+\author{Tarek Ziad�}
+
+\begin{document}
+
+\chapter*{Trouver le bon rythme entre codage, documentation, tests
+fonctionnels et unitaires}
+
+\begin{problem}
+Coder, tester, coder, tester, documenter, coder...
+
+Le rythme des activit�s de d�veloppement n'est pas �vident � �quiliber pour
+un d�veloppeur novice. En fin de projet, tests et documentation passent souvent
+� la trappe, victimes du stress du d�veloppeur, qui pr�f�re �courter ces �tapes
+pour rendre son travail dans les temps, m�me si il sait pertinement qu'il le
+payera par la suite. Ces p�riodes sont pourtant les plus importantes
+pour le code (remaniement d'API, suppression de pans complets de code, etc..)
+
+Il est possible de limiter ces ph�nom�nes et gagner en efficacit�, par de
+bonnes pratiques d�crites dans cette recette. Elles s'appliquent �videmment
+� Zope, mais peuvent �tre utilis�es dans n'importe quel projet Python.
+\end{problem}
+
+\begin{solution}
+\section*{Comprendre les r�les du d�veloppeur}
+
+Le d�veloppeur, dans la quasi totalit� des projets, a trois activit�s:
+\begin{itemize}
+\item D�velopper;
+\item documenter;
+\item tester;
+\end{itemize}
+
+La premi�re phase consiste bien s�r � cr�er le code. Un cycle de tests
+fonctionnels plus pouss�s peut suivre cette phase, puis un retour vers
+le d�veloppement est envisageable, pour des modifications, �volutions ou
+d�bugguages. Ces cycles de vie logiciels sont plus ou moins �quivalents
+dans toutes les m�thodologies existantes, comme le RUP*. Ce sujet d�passe
+cependant le cadre de ce livre.
+
+\section*{Cr��r le code}
+
+Pour con�evoir une fonctionnalit�, un d�veloppeur r�cup�re un cahier des
+charges, compos� de sp�cifications fonctionnelles, et parfois de sp�cifications
+techniques. En se basant sur ce document, la cr�ation du code s'effectue en
+trois �tapes:
+\begin{itemize}
+\item Transcrire le cahier des charges en fichier texte (doctest);
+\item ins�rer des exemples de codes dans ce texte, qui r�pond aux besoins;
+\item d�velopper le code sous-jacent aux exemples.
+\end{itemize}
+
+\subsection*{Transcrire le cahier des charges en doctest}
+
+Transcrire en doctest les besoins exprim�s se fait en synth�sant au maximum le
+cahier des charges, et en d�crivant la structure du paquet qui va �tre
+d�velopp�.
+
+Prenons l'exemple d'un module en charge de r�cup�rer des flux rss pour les
+stocker dans des objets Python persistents, puis les rendre affichables dans
+l'application. Le d�veloppeur d�cide d'organiser son paquet en trois modules:
+\begin{itemize}
+\item \code{rssfetcher.py}: module en charge de la r�cup�ration des flux RSS;
+\item \code{rssobject.py}: module en charge de la cr�ation et du stockage
+des donn�es;
+\item \code{rssview.py}: module en charge de l'affichage des donn�es.
+\end{itemize}
+
+\noindent Il commence par �crire quatre fichiers doctests, qui expriment cette
+structure:
+\begin{itemize}
+\item \code{README.txt}
+\item \code{rssreader.txt}
+\item \code{rssobject.txt}
+\item \code{rssview.txt}
+\end{itemize}
+
+Le fichier \code{README.txt} d�crit en quelques phrases l'objectif du paquet,
+et pr�sente sa structure.
+
+\codetitle{Fichier README.txt}
+\begin{verbatim}
+rssreader
+=========
+
+Ce paquet permet de pr�senter des flux rss. Il est organis� en trois
+composants:
+
+- rssreader: sait lire un flux RSS 1.0
+- rssobject: stocke le flux et fourni des m�thodes d'acc�s
+- rssview: sait afficher un flux dans le naviguateur
+\end{verbatim}
+
+\noindent Chaque module est pr�sent� � son tour dans un doctest.
+
+\codetitle{Fichier rssreader.txt}
+\begin{verbatim}
+rssfetcher
+==========
+
+Le module rssreader transforme un fichier xml au format RSS 1.0
+vers une structure Python exploitable. Il est invoqu� avec l'URL
+d'un flux et renvoi une liste contenant les entr�es du flux.
+\end{verbatim}
+
+A ce stade, le d�veloppeur n'a pas encore �crit de code, mais
+dispose d'une sp�cification technique et architecturelle exploitable.
+
+\subsection*{Ins�rer des exemples de codes}
+
+Sur la base de ces fichiers textes, le d�veloppeur peut commencer
+� pr�parer le d�veloppement des modules, en explicitant la face
+visible de ces derniers, c'est � dire les API qui seront utilis�es
+dans d'autres modules.
+
+\codetitle{Modification du fichier rssreader.txt}
+\begin{verbatim}
+rssfetcher
+==========
+
+Le module rssfetcher transforme un fichier xml au format RSS 1.0
+vers une structure Python exploitable. Il est invoqu� avec l'URL
+d'un flux et renvoi une liste contenant les entr�es du flux.
+
+Il fourni une fonction `fetchFeed(source)` qui renvoie une structure Python
+en fonction d'une url ou d'un fichier ::
+
+    >>> from rssfetcher import fetchFeed
+    >>> fetchFeed('tests/rss.xml')
+    [{'Subject': 'entry one', 'content': "le contenu est ici"}]
+\end{verbatim}
+\begin{codenotes}
+\item Le paquet doit pr�voir dans un sous r�pertoire un fichier
+�chantillon \code{rss.xml}, contenant un flux utilis� pour les tests.
+\end{codenotes}
+
+\noindent Ce principe est appliqu� pour l'ensemble des modules du paquet,
+susceptibles de fournir des fonctionnalit�s.
+
+\subsection*{D�velopper les fonctionnalit�s}
+
+Le doctest pr�c�dent ne peut bien s�r fonctionner que si l'impl�mentation
+est r�alis�e. Le d�veloppeur con�oit donc le module \code{rssfetcher.py}
+jusqu'� ce que le test du doctest passe. Ce d�veloppement n�cessitera
+certainement la cr�ation d'autres tests unitaires, qui seront
+con�us classiquement dans des classes dans le sous-r�pertoire de \code{tests}.
+
+Lorsque tous les modules sont con�us, \code{README.txt} contient un exemple
+complet d'utilisation, qui simule g�n�ralement quelques directives ZCML
+et quelques �changes avec le publisher.
+
+\section*{Maintenir et faire �voluer le code}
+
+L'�volution du paquet, que ce soit dans le cadre d'une correction, ou
+d'une modification, doit se faire de la m�me mani�re: les fichiers textes
+sont revus en premiers, puis le code est modifi� en cons�quence.
+
+Les corrections de bugs sont trait�s d'une mani�re particuli�re:
+un test unitaire qui reproduit le probl�me est ajout� dans les classes de
+tests, et le code invoqu� corrig�. Ajouter ces tests dans les doctests
+d�nature leur objectif secondaire: servir de documentation.
+
+Cependant, si il est explicitement demand� que les bugfix soient document�s,
+et facilement lisibles, un doctest \code{bugfix.txt} peut �tre ajout�.
+Ce n'est pas le cas pour Zope 3 par exemple, car le couple trac+svn fourni
+une bonne tracabilit� des bugfix.
+\end{solution}
+
+\end{document}

Added: cookbook/trunk/recipe51.fr.tex
==============================================================================
--- (empty file)
+++ cookbook/trunk/recipe51.fr.tex      Fri Mar 10 18:05:25 2006
@@ -0,0 +1,29 @@
+\documentclass{book}
+\pagestyle{headings}
+\include{macros}
+\status{draft}
+\author{Tarek Ziad�}
+
+\begin{document}
+
+\chapter*{Enregistrer une session utilisateur pour les tests}
+
+\begin{problem}
+L'�criture d'un test fonctionnel est en souvent dict� par un sc�nario
+d'utilisation pr�cis, ou "user story", o� chaque �tape est r�alis�e via
+l'interface homme-machine fournie. Dans notre cas, l'interface est bien
+s�r le naviguateur.
+
+Programmer une session web compl�te par code est fastidieux.
+
+Cette recette pr�sente des techniques pour enregistrer des actions r�alis�es
+dans un vrai naviguateur, et les r�cup�rer pour les tests fonctionnels.
+\end{problem}
+
+\begin{solution}
+TODO
+\end{solution}
+
+\end{document}
+
+

Modified: cookbook/trunk/recipe7.fr.tex
==============================================================================
--- cookbook/trunk/recipe7.fr.tex       (original)
+++ cookbook/trunk/recipe7.fr.tex       Fri Mar 10 18:05:25 2006
@@ -11,35 +11,217 @@
 \begin{problem}
 Les tests fonctionnels, ou "acceptance tests", sont compl�mentaires aux
 tests unitaires: ce sont des bo�tes noires qui testent les fonctionnalit�s
-du syst�me complet, conform�ment � chaque besoin �nonc� par le commanditaire.
+du syst�me complet, conform�ment � chaque besoin �nonc�.
 
 Ces tests ne se concentrent que sur l'utilisation du syst�me, comme le ferait
 un utilisateur lambda, pour s'assurer que les fonctionnalit�s attendues sont
 pr�sentes et fonctionnent.
 
-Ils deviennent �galement un t�moin de qualit� in�galable pour le commanditaire,
-qui peut parfois �crire ou �tendre lui-m�me ces tests.
+Ils deviennent �galement un t�moin de qualit� in�galable pour l'utilisateur
+final, qui peut parfois �crire ou �tendre lui-m�me ces tests.
+
+En terme de proportion, il est admis qu'un syst�me devrait avoir
+approximativement 2/3 de tests unitaires et 1/3 de tests fonctionnels, ces
+derniers �tant de plus haut niveau.
 
 Pour les applications web, ces tests n�cessitent un environnement d'ex�cution
-particulier, qui imite au mieux un naviguateur. C'est l'objectif du paquet
-`zope.testbrowser`, qui fourni des outils pour �crire des tests fonctionnels
-bas�s sur des �changes avec un naviguateur simul�.
+particulier, qui imite au mieux un naviguateur, et fourni des APIs pour
+effectuer des requ�tes et �tudier les r�ponses, comme le ferait Firefox
+ou Internet Explorer.
 \end{problem}
 
 \begin{solution}
 
-\section*{Principes et fonctionnement de testbrowser}
-
-todo
-
-\section*{Simuler une session utilisateur}
-
-todo
-
-\section*{Limitations de testbrowser}
-
-todo
-
+\section*{Comprendre le fonctionnement}
+Un test fonctionnel par d�finition, ne se concentre que sur les fonctionnalit�s
+d'une application, sans se soucier des d�tails d'impl�mentation, contrairement
+aux tests unitaires. C'est le test pratiqu� par l'utilisateur final, qui peut
+par exemple parcourir les menus de l'application, pour tester chacun d'entre
+eux. Il valide alors, muni d'une checklist, que chaque fonctionnalit� attendue
+est bien pr�sente et se comporte comme souhait�. Le syst�me est alors "valid�"
+si la checklist n'a aucun point manquant ou non conforme.
+
+Les tests fonctionnels en Python et a fortiori avec Zope, se font par le
+biais de classes de tests d�riv�es des classe de tests unitaires, ou
+dans des doctests.
+
+Entre tests unitaire et fonctionnel, seule l'interface entre le syst�me et le
+testeur change: ce dernier doit se mettre dans les m�mes conditions que
+l'utilisateur.
+
+\subsection*{Faire des tests fonctionnels avec des classes}
+
+Zope fourni un module sp�cifique dans le paquet \code{zope.app.testing} appel�
+\code{functional}, qui fournit des classes d�riv�es de
+\code{unittest.TestCase}. La classe la plus utilis�e est
+\code{BrowserTestCase}.
+
+\noindent Elle fournit principalement les m�thodes suivantes:
+\begin{itemize}
+\item \code{getRootFolder()}: renvoie le dossier racine de Zope. Utilis�
+pour manipuler le site avant d'analyser une publication.
+\item \code{publish(path, basic=None)}: renvoie le rendu d'un objet pour le
+chemin \code{path} sous la forme d'un objet \code{Response}. Si \code{basic}
+est fourni, c'est une cha�ne contenant le login et le mot de passe, sous la
+forme \code{'login:password'}. La cha�ne 'mgr:mgrpw' peut �tre employ�e
+pour s'authentifier avec les droits manager.
+\item \code{checkForBrokenLinks(body, path, basic=None)}: v�rifie que
+\code{body}, qui est une cha�ne de caract�re repr�sentant le corps d'une
+r�ponse (r�cup�r� par \code{Response.getBody()}), ne contient pas de
+liens cass�s. \code{path} fourni le chemin relatif qui correspond � l'objet �
+l'origine de la r�ponse. Ce param�tre permet � la m�thode de se rep�rer sur
+le site pour les r�f�rences relatives.
+\end{itemize}
+
+L'object \code{Response} est un objet renvoy� par le publisher et augment�
+par les outils de tests de quelques m�thodes facilitant la lecture. On
+retiendra surtout:
+\begin{itemize}
+\item \code{getBody()}: renvoie le corps de la r�ponse
+\item \code{getOutput()}: renvoie la r�ponse compl�te (corps et en-t�tes)
+\item \code{getStatus()}: renvoie le status
+\item \code{getHeaders()}: permet de r�cuperer les headers
+\end{itemize}
+
+Dans l'exemple ci-dessous, un dossier est cr�� dans le dossier racine,
+et son rendu v�rifi�.
+
+\codetitle{Classe de v�rification du rendu d'un dossier:}
+\begin{Verbatim}
+>>> import transaction
+>>> from zope.app.testing import functional
+>>> from buddydemo.buddy import BuddyFolder
+>>> class FolderTest(functional.BrowserTestCase):
+...     def test_folder(self):
+...         root = self.getRootFolder()
+...
+...         # create a Folder
+...         root['cool_folder'] = BuddyFolder()
+...         transaction.commit()
+...
+...         # get the root content through the publisher
+...         response = self.publish('/cool_folder', basic='mgr:mgrpw')
+...         self.assert_('<title>Z3: cool_folder</title>' in
+...                      response.getBody())
+\end{Verbatim}
+\begin{codenotes}
+\item Le code \code{transaction.commit()} permet de valider la modification
+effectu�e sur le site, pour la rendre disponible lors de l'appel �
+\code{publish}.
+\end{codenotes}
+
+Ce test est ex�cut� comme un test unitaire classique.
+
+\codetitle{Lancement du test:}
+\begin{Verbatim}
+>>> import unittest
+>>> suite = unittest.makeSuite(FolderTest)
+>>> test_runner = unittest.TextTestRunner()
+>>> test_runner.run(suite)
+<unittest._TextTestResult run=1 errors=0 failures=0>
+\end{Verbatim}
+
+\subsection*{Faire des tests fonctionnels par doctests}
+
+Les tests fonctionnels sont des tests de tr�s haut niveau, et se rapprochent
+beaucoup des exemples de code qu'une documentation peut contenir. Il est
+possible en Python d'associer ce besoin documentaire avec les tests par
+le biais des doctests.
+
+\subsubsection*{Comprendre les doctests de Python}
+
+L'originalit� de Python est de fournir un syst�me de tests bas� sur les
+docstrings: le code a tester est �crit dans des docstrings, sous la
+forme de s�quences de prompt Python.
+
+\codetitle{Exemple de doctest:}
+\begin{Verbatim}
+>>> def laVerite():
+...     """
+...     >>> laVerite()
+...     'les doctests, ca claque'
+...     """
+...     return 'les doctests, ca claque'
+\end{Verbatim}
+
+Le module \code{doctest} de Python fourni des outils pour extraire et ex�cuter
+ces tests.
+
+\codetitle{Execution du doctest:}
+\begin{Verbatim}
+>>> import doctest
+>>> doctest.run_docstring_examples(laVerite, globals(), verbose=True)
+Finding tests in NoName
+Trying:
+    laVerite()
+Expecting:
+    'les doctests, ca claque'
+ok
+\end{Verbatim}
+
+Cependant, les tests contenus dans les doctests de chaque module,
+classe et fonction parasitent la lisibilit� du code. Pour �viter cette
+obfuscation, il est possible de les regrouper dans un fichier texte s�par� du
+code, et "ex�cuter" ce fichier. Les exemples peuvent alors �tre agr�ment�s
+d'explications et suivre un d�roulement logique. On parle alors de
+"documentation agile", ou "documentation ex�cutable".
+
+Ces documents peuvent ensuite �tre appel�s comme module de test.
+
+\codetitle{Document agile:}
+\begin{verbatim}
+Le module verite
+================
+
+Ce document ne contient pas de tests fonctionnels mais plut�t un test unitaire.
+
+Ce n'est pas bien grave.
+
+Le module v�rit� contient une fonction `laVerite()` qui peut �tre appel�e
+pour afficher un message. Cette m�thode ne sert pas � grand chose.
+
+Exemple d'utilisation::
+
+  >>> from verite import laVerite
+  >>> laVerite()
+  'les doctests, ca claque'
+\end{verbatim}
+
+\subsubsection*{Comprendre les doctests fonctionnels dans Zope}
+
+Pour manipuler facilement Zope dans les doctests, le paquet
+\code{zope.testbrowser} fourni une classe \code{Browser} qui permet
+de simuler un naviguateur et ses fonctionalit�s. Par convention, cette classe
+est invoqu�e avec une URL qui commence par \url{http://localhost}, puis le
+chemin sur le serveur Zope.
+
+Atteindre la page � la racine peut donc s'�crire ainsi:
+\begin{Verbatim}
+>>> from zope.testbrowser.testing import Browser
+>>> browser = Browser('http://localhost')
+>>> browser.url
+'http://localhost'
+>>> browser.contents
+'...<title>Z3: </title>...'
+\end{Verbatim}
+\begin{codenotes}
+\item La propri�t� \code{contents} permet de r�cup�rer le contenu de la page 
sous
+forme d'une cha�ne de caract�res.
+\item Les '...' (ou Ellipsis) ont une signification pr�cise dans les doctests:
+ils servent � remplacer une portion de texte quelconque. Dans l'exemple ci
+dessus, ils permettent de s'assure que \code{contents} contient bien la portion
+HTML indiqu�e.
+\end{codenotes}
+
+AFINIR ici
+
+\section*{Limitations des tests fonctionnels}
+
+Les tests fonctionnels web ont une limitation inh�rente au fonctionnement des
+naviguateurs: il est impossible de tester le javascript contenu dans les pages
+car chaque naviguateur impl�mente son propre moteur. Il faut utiliser d'autres
+techniques, bas�es par exemple sur le syst�me de test \textit{Selenium}, qui
+lance les tests depuis un naviguateur r�el.
 \end{solution}
 
 \end{document}

Modified: cookbook/trunk/recipe_list.txt
==============================================================================
--- cookbook/trunk/recipe_list.txt      (original)
+++ cookbook/trunk/recipe_list.txt      Fri Mar 10 18:05:25 2006
@@ -32,7 +32,7 @@
 04 - the zope component architecture
 05 - understanding the development process
 06 - writing unit tests
-07 - writing functional tests
+07 - writing functional tests (TZ)
 08 - debugging the code
 09 - understanding Interfaces
 10 - understanding the traversal
@@ -61,6 +61,15 @@
 45 - creating an internationalized package
 46 - creating multilanguage content objects
 47 - changing and migrating existing objects
+48 - writing reSTructuredText for documentation and doctests  (TZ)
+49 - using zapi in tests  (TZ)
+50 - organizing tests in a package  (TZ)
+51 - finding the good pace between coding, documenting, unit testing and
+     functionnal testing  (TZ)
+52 - recording a user web session to write tests  (TZ)
+53 - organizing the code in a package  (TZ)
+54 - using ldap to store users
+55 - using a sql database to store data
 - ...
 
 Developping Zope - advanced recipes

Modified: cookbook/trunk/tests.py
==============================================================================
--- cookbook/trunk/tests.py     (original)
+++ cookbook/trunk/tests.py     Fri Mar 10 18:05:25 2006
@@ -1,38 +1,83 @@
+# -*- coding: ISO-8859-15 -*-
+# Copyright (c) 2004 Tarek Ziad� and contributors
+# Author: Tarek Ziad� <[EMAIL PROTECTED]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+""" run all latex recipes files contained in the
+    current directory as functionnal doctests,
+    using zope environnement
+"""
 import doctest
 import os
 import unittest
-import re
+from zope.app.testing import setup, functional
+from textest import TexFileSuite
 
+def FunctionalTexFileSuite(filename, **kw):
+    globs = kw.setdefault('globs', {})
+    globs['http'] = functional.HTTPCaller()
+    globs['getRootFolder'] = functional.getRootFolder
+    globs['sync'] = functional.sync
+    kw['package'] = doctest._normalize_module(kw.get('package'))
+
+    kwsetUp = kw.get('setUp')
+    def setUp(test):
+        functional.FunctionalTestSetup().setUp()
+        setup.setUpTestAsModule(test, filename.replace('.', '_'))
+        if kwsetUp is not None:
+            kwsetUp(test)
+
+    kw['setUp'] = setUp
+
+    kwtearDown = kw.get('tearDown')
+    def tearDown(test):
+        if kwtearDown is not None:
+            kwtearDown(test)
+        try:
+            setup.tearDownTestAsModule(test)
+        except KeyError:
+            # XXX see why
+            pass
+        functional.FunctionalTestSetup().tearDown()
+
+    kw['tearDown'] = tearDown
+
+    if 'optionflags' not in kw:
+        old = doctest.set_unittest_reportflags(0)
+        doctest.set_unittest_reportflags(old)
+        kw['optionflags'] = (old
+                             | doctest.ELLIPSIS
+                             | doctest.REPORT_NDIFF
+                             | doctest.NORMALIZE_WHITESPACE)
+
+    suite = TexFileSuite(filename, **kw)
+    suite.layer = functional.Functional
+    return suite
 
-extracter = r'\\begin{Verbatim}(?P<contents>.*?)\\end{Verbatim}'
-cExtracter = re.compile(extracter, re.MULTILINE| re.DOTALL)
 
 current_folder = os.path.dirname(__file__)
 if current_folder == '':
     current_folder = '.'
 
-
 def test_suite():
-    options = doctest.ELLIPSIS
     extractor = doctest.DocTestParser()
-    tests = []
-
-    for file in os.listdir(current_folder):
-        if not file.endswith('.tex'):
-            continue
-
-        content = open('%s/%s' % (current_folder, file)).read()
-        match_obj = cExtracter.search(content)
-        if match_obj is None:
-            continue
-
-        content = match_obj.group('contents').strip()
-
-        file_tests = extractor.get_doctest(content, globals(), file, file,
-                                           None)
 
-        tests.append(doctest.DocFileCase(file_tests))
+    files = [file for file in os.listdir(current_folder)
+             if file.endswith('.tex')]
 
+    tests = [FunctionalTexFileSuite(file) for file in files]
     return unittest.TestSuite(tests)
 
 if __name__ == '__main__':

Added: cookbook/trunk/tests.txt
==============================================================================
--- (empty file)
+++ cookbook/trunk/tests.txt    Fri Mar 10 18:05:25 2006
@@ -0,0 +1,41 @@
+Latex test environment
+______________________
+
+The textest and tests modules are used by Zope 3 test script.
+
+Each latex file in this folder is ran like a doctest, with a filtering of the
+text content, wich is based on the extraction of `Verbatim` sections.
+
+`verbatim` sections are not run on purpose, so your latex files
+can contain examples you don't want to run in tests.
+
+If you create classes in your latex file, and you need to reach them for
+example in a zcml class directive, the module name is the file name,
+with dots replaced by underlines.
+
+For example, in recipeX.fr.tex::
+
+    >>> class FolderListing:
+    ...     def contents(self):
+    ...         return list(self.context.keys())
+    >>> from zope.configuration import xmlconfig
+    >>> ignored = xmlconfig.string("""
+    ... <configure
+    ...     xmlns="http://namespaces.zope.org/zope";
+    ...     xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc";
+    ...     >
+    ...   <include package="zope.app.publisher.xmlrpc" file="meta.zcml" />
+    ...
+    ...   <xmlrpc:view
+    ...       for="zope.app.folder.folder.IFolder"
+    ...       methods="contents"
+    ...       class="recipeX_fr_tex.FolderListing"
+    ...       permission="zope.ManageContent"
+    ...       />
+    ... </configure>
+    ... """)
+
+
+
+
+

Added: cookbook/trunk/textest.py
==============================================================================
--- (empty file)
+++ cookbook/trunk/textest.py   Fri Mar 10 18:05:25 2006
@@ -0,0 +1,71 @@
+# -*- coding: ISO-8859-15 -*-
+# Copyright (c) 2004 Tarek Ziad� and contributors
+# Author: Tarek Ziad� <[EMAIL PROTECTED]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+""" textest is similar to doctest but to be used
+    with latex files.
+"""
+import doctest
+import os
+import unittest
+import re
+import sys
+from StringIO import StringIO
+import pdb
+
+extracter = r'\\begin{Verbatim}(?P<contents>.*?)\\end{Verbatim}'
+cExtracter = re.compile(extracter, re.MULTILINE| re.DOTALL)
+
+def _latexfilter(source):
+    code_blocs = cExtracter.findall(source)
+    if code_blocs == []:
+        return source
+    return ''.join(code_blocs).strip()
+
+def TexFileTest(path, module_relative=True, package=None,
+                globs=None, parser=doctest.DocTestParser(), **options):
+    if globs is None:
+        globs = {}
+
+    if package and not module_relative:
+        raise ValueError("Package may only be specified for module-"
+                         "relative paths.")
+
+    # Relativize the path.
+    if module_relative:
+        package = doctest._normalize_module(package)
+        path = doctest._module_relative_path(package, path)
+
+    # Find the file and read it.
+    name = os.path.basename(path)
+    doc = open(path).read()
+    doc = _latexfilter(doc)
+
+    # Convert it to a test, and wrap it in a DocFileCase.
+    test = parser.get_doctest(doc, globs, name, path, 0)
+    return doctest.DocFileCase(test, **options)
+
+
+def TexFileSuite(*paths, **kw):
+    suite = unittest.TestSuite()
+
+    if kw.get('module_relative', True):
+        kw['package'] = doctest._normalize_module(kw.get('package'))
+
+    for path in paths:
+        suite.addTest(TexFileTest(path, **kw))
+
+    return suite
-- 
http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins

Reply via email to