|
|
|
@ -0,0 +1,779 @@
|
|
|
|
|
% Préambule
|
|
|
|
|
\documentclass[12pt]{article}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\title{Rapport de stage Point}
|
|
|
|
|
\author{Point}
|
|
|
|
|
|
|
|
|
|
\usepackage[utf8]{inputenc}
|
|
|
|
|
\usepackage{hyperref}
|
|
|
|
|
\usepackage{graphicx}
|
|
|
|
|
\usepackage{float}
|
|
|
|
|
\usepackage[a4paper]{geometry}
|
|
|
|
|
\geometry{verbose,tmargin=2cm,bmargin=2cm,lmargin=2.5cm,rmargin=2cm}
|
|
|
|
|
\usepackage[export]{adjustbox}
|
|
|
|
|
\usepackage{url}
|
|
|
|
|
\renewcommand{\contentsname}{Sommaire}
|
|
|
|
|
\graphicspath { {./images/} }
|
|
|
|
|
\usepackage[
|
|
|
|
|
type={CC},
|
|
|
|
|
modifier={by-nc-sa},
|
|
|
|
|
version={3.0},
|
|
|
|
|
]{doclicense}
|
|
|
|
|
|
|
|
|
|
\hypersetup{
|
|
|
|
|
colorlinks=true,
|
|
|
|
|
linkcolor=blue,
|
|
|
|
|
filecolor=magenta,
|
|
|
|
|
urlcolor=blue,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
%-----------------------------------
|
|
|
|
|
|
|
|
|
|
\begin{document}
|
|
|
|
|
\begin{titlepage}
|
|
|
|
|
\newcommand{\HRule}{\rule{\linewidth}{0.5mm}}
|
|
|
|
|
\center
|
|
|
|
|
\textsc{\LARGE
|
|
|
|
|
Institut Universitaire de Technologie d'Aubière
|
|
|
|
|
} \\[1cm]
|
|
|
|
|
\includegraphics[width=\textwidth]{iut} \\[1cm]
|
|
|
|
|
\HRule \\[0.4cm]{ \huge \bfseries Rapport de stage\\[0.30cm] }
|
|
|
|
|
{ \Large \bfseries Réalisation d’une suite de tests comportementauxautour de l’infrastructure logicielle de Résif-DC dédiée à la livraison de données et métadonnées sismologiques\\[0.15cm] }
|
|
|
|
|
\HRule \\[1.5cm]
|
|
|
|
|
\includegraphics[scale=0.4]{isterre} \\[1cm]
|
|
|
|
|
\includegraphics[scale=1]{resif} \\[1cm]
|
|
|
|
|
\vspace*{\fill}
|
|
|
|
|
présenté par: \textbf{Allan POINT}
|
|
|
|
|
\end{titlepage}
|
|
|
|
|
\newpage{}
|
|
|
|
|
\begin{center}
|
|
|
|
|
\vspace*{\fill}
|
|
|
|
|
\framebox{J'autorise la diffusion de mon rapport sur l'intranet de l'IUT}
|
|
|
|
|
\vspace*{\fill}
|
|
|
|
|
\doclicenseThis
|
|
|
|
|
\end{center}
|
|
|
|
|
\newpage{}
|
|
|
|
|
\textbf{\huge Remerciements}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Je souhaite remercier tout les membres de ISTerre pour avoir pu m'acceuillir dans les meilleures conditions ainsi que toutes le personnes m'ayant aidé ou ayant proposé leur aide à la réalisation de ce rapport.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Je souhaite remercier toute l'équipe RÉSIF-DC avec qui j'ai pu travailler.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Je souhaite aussi remercier mon tuteur de stage, \textit{Philippe BOLLARD}, pour avoir su m'encadrer et m'aider dans les dfficultés que j'ai pu rencontrer lors du stage.
|
|
|
|
|
\newpage
|
|
|
|
|
\tableofcontents
|
|
|
|
|
\newpage{}
|
|
|
|
|
\section{Introduction}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
La sismologie est une dicipline scientifique visant à étudier le comportement de la Terre lors de séismes ainsi que la propagation des ondes élastiques (sismiques) à l'interieur la planète\cite{sismo}. En effet, la Terre est constament en train de trembler. Il est donc important pour les chercheur\textperiodcentered euse\textperiodcentered s d'avoir accès rapidement et facilement aux données mesurant l'activité sismique de la Terre et aux conditions de récolte de ces données pour créer de nouvelles connaissances sur la structure de la Terre mais aussi pour pouvoir anticiper l'arrivée de catastophes dues au séisme. C'est pour cela que de nombreux capteurs, mesurant diverses unités physique telles que la vitesse ou l'accélération, sont installés un peu partout autour du globe, surveillent en permanence le comportement de la Terre. Ansi, c'est donc dans l'horizon d'une distribution parfaite des données que s'inscrit mon stage à ISTerre.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
ISTerre est un laboratoire universitaire à Grenoble dont le but est l'étude de la sismologie\cite{isterrePlaquette}. Ce laboratoire héberge une équipe d'informaticien\textperiodcentered ne\textperiodcentered s, nommée RÉSIF-DC, dont l'objectif est de développer et maintenir le centre de donnée RÉSIF en s'appuiyant sur les ressources de l'Université Grenoble Alpes (UGA)\cite{resifSI}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Résif est une Infrastructure de Recherche (IR) qui déploie en France métropolitaine une instrumentation moderne (parcs de sismomètres, stations GNSS et gravimètres) qui mesure la déformation de la surface terrestre\cite{resifHome}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
J'ai donc pu effectuer mon stage dans ce contexte, dans le cadre d'une optimisation des \textit{web services} RÉSIF.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
L'objectif de mon stage était donc de construir des tests comportementaux sur plusieurs de ces \textit{web services}, à savoir les services \href{https://ws.resif.fr/fdsnws/station/1}{'station'}, \href{https://ws.resif.fr/fdsnws/dataselect/1}{'dataselect'} et \href{https://ws.resif.fr/fdsnws/availability/1}{'availability'}. En effet, les tests que j'ai implémenté auront pour utilité de comparer les performances, la non-régréssion entre les nouvelles et anciennnes versions de ces \textit{web services} ainsi que la conformité de ces \textit{web services} face aux spécifications établies par la communauté scientifique. La problématique de ce stage est donc comment réaliser des tests exhaustifs qui permettent de mettre en lumière les problemes des \textit{web services} de résif.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Dans ce rapport, j'exposerai d'abord les structures qui m'ont acceuilli et entouré lors de la réalisation de mon stage. Ensuite, je décrirai le contexte dans le quel j'ai baigné pendant 10 semaines. Après cela que je détaillerai le déroulement de ce stage, depuis la gestion de projet jusqu'à la réalisation finale en passant par les problèmes rencontrés. Enfin, je ferai un bilan sur ce que j'ai pu réaliser avant de conclure.
|
|
|
|
|
\newpage{}
|
|
|
|
|
|
|
|
|
|
\section{Structures d'acceuil}
|
|
|
|
|
\subsection{Présentation des structures d'accueil}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
RÉSIF-DC est géré par différents organismes qui sont sous la tutelle du ministère de la transition écologique ainsi que par le ministère de l'enseignement supperieur, de la recherche et de l'inovation\cite{resifOrga}. Quand j'ai signé ma convention, je l'ai fait avec l'Unitée Mixte de Recherche (UMR) ISTerre. En effet, le bureau dans lequel je travaillais se situait dans les locaux de cette UMR. Toutefois, le personnel travaillant dans l'équipe RÉSIF-DC est sous la direction de l'OSUG et de RÉSIF-EPOS. Ainsi, j'ai été amené a integrer une équipe d'ingénieurs OSUG (cf. Figure~\ref{fig:orgaResifDC}).
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Répartition des organismes contribuant à RÉSIF-DC}
|
|
|
|
|
\includegraphics[width=\textwidth]{organigrame}
|
|
|
|
|
\label{fig:orgaResifDC}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\subsection{RÉSIF-EPOS}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Le réseau sismologique et géodésique français (RÉSIF) est un consortium réunissant 18 institutions\cite{resifOrga}. RÉSIF c'est aussi une Infrastructure de Recherche (IR) regroupant des chercheur\textperiodcentered euse\textperiodcentered s qui étudient les données récoltées pour comprendre la dynamique et les aléas de l'interieur de notre planète ainsi que les interactions atmosphère/océan\cite{resifHome}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
L'infrastructure est née d'un besoin de prévention dans le cadre de secousses sismiques. Historiquement, c'est le séisme de Teil (2019), près de Castres, qui a confirmé la vulnérabilité de la France faces aux aléas sismiques de par son impact social et éconimique\cite{resifPres}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Ainsi, RÉSIF contribue
|
|
|
|
|
à l'évaluation des aléas et des risques liés à une activité sismique,
|
|
|
|
|
à l'évaluation rapide des dégâts,
|
|
|
|
|
à la gestion de crises,
|
|
|
|
|
aux normes de construction des bâtiments,
|
|
|
|
|
à l'établissement d'un lien entre les dégâts sur un immeuble et la sismicité,
|
|
|
|
|
à l'évaluation des secousses induites par l’activité humaine, etc.\cite{resifPres}.
|
|
|
|
|
\subsubsection{RÉSIF-SI}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
RÉSIF-SI est une action transverse, impliquant ingénieur\textperiodcentered e \textperiodcentered s et scientifiques provenant de plusieurs laboratoires et observatoires tel que l'Institut de Physique du Globe de Paris (IPGP), l'Observatoire des Sciences de l'Univers de Grenoble (OSUG), ISTerre et bien d'autres \cite{resifSI}. Sont but est la collecte, le formatage, la validation et la qualifiquation de données sismiques, la génération de méta-données, l'archivage des données/méta-données ainsi que leurs distribution. Ainsi, un ensemble de capteurs géophysiques implantés partout en France est maintenu par RÉSIF-SI. Ces capteurs sont répartis en plusieurs réseaux tel que le \href{https://rap.resif.fr}{Réseau d'acelerométrie Permanant} (RAP) ou le \href{https://sismob.resif.fr}{parc national Sismologique Mobile} (SisMob)\cite{resifSI}. Ces capteurs permettent d’alimenter, en partie, l’infrastructure EPOS (European Plate Observing System). RÉSIF-SI, c'est l'organisme majeur qui contibue à cette alimentation. Ainsi les données collectées par RÉSIF sont disponible via plusieurs \textit{web services} qui sont standardisés par plusieurs organismes tel que EIDA, FDSN et RÉSIF même.\cite{resifSI}
|
|
|
|
|
\subsection{L'OSUG}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
L'Observatoire des Sciences de l'Univers de Grenoble fédère des laboratoires pour permettre à la recherche dans les sciences de l'Univers, de la Terre et de l'environnement, une communication plus facile, une répartition des tâches efficace et une collaboration favorisée\cite{osugHome}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Ainsi, l'OSUG permet aux insitituts d'avoir du personnel qualifié pour pouvoir assurer une mission d'observation grâce à ces Unités d'Appui et de Recherche (UAR) dont fait partie l'OSUG-DC\cite{osugOrga}.
|
|
|
|
|
\subsubsection{OSUG-DC}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
L'OSUG-DC est une équipe formée principalement d'ingénieur\textperiodcentered e \textperiodcentered s en informatiques s'assurant du traitement et de la diffusion de données d'observations. L'équipe a aussi pour mission de concevoir et développer des logiciels qui seront mis à disposition de la communauté scientifique\cite{osugDC}.
|
|
|
|
|
\subsubsection{RÉSIF-DC}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Ainsi, des membres de l'OSUG-DC forment l'équipe RÉSIF-DC, chargée de développer et maintenir les \textit{web services} RÉSIF. C'est dans ce cadre que s'inscrit mon stage et c'est dans ce contexte que j'ai interagi avec les membres de l'équipe.
|
|
|
|
|
\subsection{ISTerre}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
ISTerre (Instutut des Sciences de la Terre) est un laboratoire créé en 2011, fédéré par l'OSUG\cite{isterreEnBref}, dont l’objectif scientifique est l’étude physique et chimique de notre planète\cite{isterrePlaquette}. Le laboratoire est réparti sur deux villes, Chambery et Grenoble. Le nombre de personnes travaillant pour ce laboratoire est assez important : près de 300 personnes en additionant les 2 sites dont la pluparts sont scientifiques (20 \% du personnel sont des technicien·ne·s). Pour donner une idée du pourvoir d’action du laboratoire, celui-ci a un budget annuel d’environ 15 millions d’euros\cite{isterrePlaquette}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
ISTerre travaille en collaboration avec plusieurs pays, notamment du Sud (Équateur, Pérou, Liban, \dots). Cet collaboration est en partie traduite par l’échange de chercheur·euse·s et d’étudiant·e·s\cite{isterrePlaquette}. Le travail scientifique du laboratoire ce retrouve chaque année dans près de 250 articles de recherche et dans de nombreuses actions de vulgarisations scientifique\cite{isterrePlaquette}. Ces connaissances on put être récoltées grâce aux différentes actions menées comme des déplacements dans des lieux sismiques, la récolte et la distribution de données aquises par différents réseaux d’instruments géophysiques, l’analyse d’échantillons naturels, et grâce à de nouvelles modélisations et expérimentations\cite{isterrePlaquette}. La récolte et le traitement des données s’articule autour de trois grands axes pour ISTerre\cite{isterreScientifics} :
|
|
|
|
|
\begin{enumerate}
|
|
|
|
|
\item Peut-on identifier des précurseurs aux grands événements qui boulverssent notre planète ? Quels sont les processus physiques qui gouvernent les séismes, les mouvements de terrain, les éruptions volcaniques, les varuations du champ magnétique terrestre ?
|
|
|
|
|
\item Comment la surface de la Terre est-elle façonnée par les interactions entre les processus profonds et les processus de surface ?
|
|
|
|
|
\item Comment roches et sols enregistrent les perturbations physico-chimique naturelles ou anthropique de leur environnement ? Quelles sont les mécanismes qui gouvernent la croissance, la sorption et l’alteration des minéraux ? Comment les processus hydrothermaux et magnétiques concernent-ils les ressources minérales ? Comment produire de l’hydrogène ? La carbonatation minérale, une voie pour le stockage du CO2 ?
|
|
|
|
|
\end{enumerate}
|
|
|
|
|
|
|
|
|
|
\newpage{}
|
|
|
|
|
\section{Présentation du stage}
|
|
|
|
|
\subsection{Gestion de projet}
|
|
|
|
|
\subsubsection{Réalisé}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Sachant que j'étais sur un projet seul, le besoin de planification au long terme ne s'est pas vraiment fait ressentir. En effet, ce genre de methode est très utile dans les projets de groupes ou les acteur\textperiodcentered ice\textperiodcentered s ont besoin de communiquer leurs avancées ainsi que le plans d'actions. Ainsi, je n'ai pas réalisé de diagramme de GANTT et c'est seuelment a posteriori que j'en ai construit un (cf. Figure \ref{fig:GANTT}). Cependant, j'ai quand même organisé mon travail en différentes tâches qui respectent un certain schéma. En effet, pour chaque \textit{web services}, je faisais une tâche \textit{Scénario} et une tâche \textit{Implémentation}. Chacune de ces tâches était elle-même divisée en sous-tâches. Par exemple, la tache \textit{Station Implementation} avait une sous-tâche nommée \textit{given the paramerter value from start to end on the level "level" [STATION]} ou encore \textit{Make xml validator computes str and not etree}.
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\label{fig:GANTT}
|
|
|
|
|
\caption{Réalisation du travail}
|
|
|
|
|
\includegraphics[width=\textwidth]{GANTT}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour organiser ces tâches, j'ai utilisé les \textit{issues} de \textit{gitlab} (cf. Chapitre~\ref{chap:gitlab}). En effet, les super tâches étaient modélisées par des \textit{labels} combinables. Par exemple, pour la tâche \textit{scenario Dataselect}, les labels étaient \textit{Scénario} et \textit{WS-Dataselect} (cf. Figure~\ref{fig:task}).
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Exemple de tâche}
|
|
|
|
|
\centering
|
|
|
|
|
\includegraphics[scale=0.5, frame]{taskGitlab}
|
|
|
|
|
\label{fig:task}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\subsubsection{Organisation de l'équipe}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
La manière dont l'équipe s'organisait était structurée de la sorte:
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item \textbf{Tous les matins}: \textit{Point avec mon tuteur de stage}: définition des objectifs du jour
|
|
|
|
|
\item \textbf{Lundi matin à 11h}: \textit{Réunion ticket}: Point sur les réalisations de la semaine précédente et explication du travail à fournir pour la semaine qui vient par et pour chaque membre de l'équipe.
|
|
|
|
|
\item \textbf{Le reste du temps}: \textit{travail individuel}: Chaque membre de l'équipe travaille sur ses tâches (seul\textperiodcentered e ou en groupe)
|
|
|
|
|
\end{itemize}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\subsection{Environnement}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Le laboratore est pricipalement constitué de chercheur\textperiodcentered euse\textperiodcentered s dans différents domaines, ce qui donne un environnement très riche où les interactions entre les membres des différents services sont assez édifantes.
|
|
|
|
|
Cependant, durant mon stage, j'étais la pluspart du temps dans un bureau avec une équipe de 4 personnes.
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item \textbf{Jonathan Schaeffer}: responsable infrastructure et coordinateur de l'équipe Résif-DC
|
|
|
|
|
\item \textbf{Phillipe Bollard}: responsable logiciel
|
|
|
|
|
\item \textbf{Thibaut Rolland}: ingénieur infrastructure
|
|
|
|
|
\item \textbf{David Wolyniec}: ingénieur expert données et responsable de l'intégration des données des noeuds A \textit{RAP} et \textit{SISMOB}
|
|
|
|
|
\end{itemize}
|
|
|
|
|
\subsection{Existant}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Quand je suis arrivé, les differents \textit{web services} que j'avais à tester été terminés et déployés par une ancienne équipe. Il existait déjà une suite de tests développée par cette même équipe. Cependant, les tests étaient effectués sans bibliothèque ou \textit{framework} de test, ce qui rendait difficile son maintient.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
En vue d'une refonte de cette suite de tests, l'équipe RÉSIF-DC avait déjà essayé différents frameworks avant de sélectionner Behave et de démarrer une première ébauche de tests autour du \textit{web service} station.
|
|
|
|
|
Cependant, pour ne pas brider ma créativité, il a été décidé que je parte de zéro et que seulement une fois que j'aurais fini d'écrire mes scénarios, je regarde les différents scénarios définis par l'équipe.
|
|
|
|
|
\subsection{Objectifs}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Les objectifs de mon stage étaient multiples. En effet, je devais développer une suite de tests capable de vérifier le comportement des \textit{web services} dans des cas de mise en difficulté ainsi que de vérifier le simple fonctionement de ces derniers. Un des effet de bord de cela est que j'ai pu détecter des bugs des \textit{web services}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Ainsi, lors d'une nouvelle implémentation d'un \textit{web service}, les résultats des requêtes peuvent être comparés. Aussi, lors d'un changement d'infrastructure, qui peuvent amener une migration des serveurs, le test du fonctionement des \textit{web services} peut être réalisé rapidement.
|
|
|
|
|
\newpage{}
|
|
|
|
|
\section{Le développement des tests}
|
|
|
|
|
\subsection{La prise en main du contexte}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Lors de ma première semaine de stage, mon principal objectif été de prendre en main le contexte dans lequel j'allais travailler. En effet, j'ai principalement lu de la documentation sur les termes techniques (glossaire), sur la sismologie, sur les standards FDSN, \dots
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Ensuite, j'ai pu commencer à prendre en main l'outil \textit{behave} et me rafraîchir la mémoire au niveau du langage \textit{python}. Après ca, j'ai pu commencer à réfléchir à des scénarios de tests. C'est ce que j'ai principalement fait pendant 3 jours. En parallèle de ca, j'ai pu prendre en main d'autre bibliothèque telles que \textit{lxml} ou \textit{requests}.
|
|
|
|
|
\subsubsection{FDSN}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
La \textit{Federation of Digital Seismograph Networks} (FDSN) est une organisation qui fedère des laboratoires de sismologie dont le but est d'installer et maintenir des stations sismologiques ausi bien nationalement qu'internationalement. La FDSN a notament normalisé la diffusion de données et méta-données par des formats tel que le \textit{MiniSEED} ou le \textit{StationXML}\cite{fdsnAbout, wikiFDSN}.
|
|
|
|
|
\subsection{Les outils utilisés}
|
|
|
|
|
\subsubsection{Python}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
\textit{Python}\cite{wikiPython} est un langage de programmation orienté objet qui est accessible à un large public. Cette accessibilité apporte certaines contraintes, notamment au niveau objet. En effet, des notions importantes du paradigme objet ne sont pas présentes, ce qui peut géner lors de la conception du logiciel.
|
|
|
|
|
\subsubsection{Pipenv}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
\textit{Pipenv}\cite{pipenvReedme} est un outil de gestion d'environement virtuel. Un environement virtuel est un ensemble de programmes qui viennent s'ajouter ou remplacer une version du même programme. En \textit{python}, cela sert principalement à importer la verssion de \textit{python} avec laquelle ont été implémentés le code et les bibliothèques utilisés par celui-ci. Ainsi, \textit{pipenv} permet d'ajouter des bibliothèques et frameworks à un environnement virtuel. Ainsi, lors du déploiement du projet, il n'y aura pas de conflit de versions ou de bibliothèques manquantes grâce à l'environnement virtuel. Autrement dit, c'est comme si la machine qui éxécute le projet avait la même configuration que la machine qui a servi à développer.
|
|
|
|
|
\subsubsection{Behave}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
\textit{Behave}\cite{behavePypi, behaveHome} est une implementation en \textit{python} de \textit{cucumber}, un framework de test comportemental. Cela permet de tester le comportement d'un logiciel sans rentrer dans le code, contrairement à d'autres types de tests tels que les tests unitaires ou les tests fonctionnels. Cela possède son lot d'avantages et d'inconvénients. Pour ce qui est des avantages, je n'ai pas eu besoin d'entrer dans le détail des \textit{web services}, d'autant plus que ces codes sont difficiles à comprendre car ils n'ont pas été codés dans un langage de programmation mais en SQL. Un des inconvénients de ce type de test est qu'il est plus difficile de repérer le morceau de code qui provoque un bug détécté par les tests comportementeaux.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Le fonctionnement du framework est assez simple. Il faut faire des fichiers de \textit{feature} écrits en langage naturel (français, anglais, mandarin, \dots). Ensuite, chaque ligne est associée à un morceau de code qui va faire les tests. Par exemple, une ligne "Étant donné le parametre network égale à FR" est associée à un bout de code qui va dire au contexte du test que le réseau à utilisé est FR.
|
|
|
|
|
\subsubsection{Git}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Git\cite{gitAbout} est un outil de gestion de version, principalement utilisé dans le développement. Il permet de pouvoir revenir à tout moment sur une version précédente du code produit pour pouvoir ainsi revenir en arrière en cas de déviation trop importante entre le code et ce qui est attendu. Git permet aussi de diviser un projet en branches, c'est à dire que plusieurs personnes peuvent collaborer sans se gêner si ces personnes se situent sur des branches différentes. Quand le travail sur deux branches est terminé, il est possible de les fusionner (\textit{merge}) pour que le projet continue avec la production des colaborateur\textperiodcentered ice\textperiodcentered s des branches fusionnées.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Une extention de git, nommé \textit{git flow}\cite{gitflow} est faite pour avoir une arborescence git optimale pour la collaboration (cf. Figure~\ref{fig:gitflow}). Elle divise le projet en deux branches: \textit{main} et \textit{develop}. La branche \textit{main} correspond au code fonctionnel, prêt à être utilisé et stable. C'est la branche à utiliser pour un\textperiodcentered e utilisateur\textperiodcentered ice lambda. La branche \textit{develop} correspond à la version instable du projet, celle qui tend à être stable. C'est la brache dans laquelle les dévloppeur\textperiodcentered{}euse\textperiodcentered s fusionnent (\textit{merge}) leur travail. Ce travail est produit dans des branches spécifiques appelées \textit{feature} qui corespond à une fonctionnalité du programme. Ainsi, les bugs dus à la progression du code de la fonctionnalité n'affecte pas les autres colaborateur\textperiodcentered ice\textperiodcentered s qui travaillent sur autre chose.
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\centering
|
|
|
|
|
\caption{Schéma du fonctionnement de git flow}
|
|
|
|
|
\includegraphics[scale=0.4]{gitflow}
|
|
|
|
|
\label{fig:gitflow}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\subsubsection{Gitlab}
|
|
|
|
|
\label{chap:gitlab}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Gitlab\cite{gitlab} est un logiciel de type serveur permettant de stocker un dêpot git et de le redistribuer ensuite. Il permet la centralisation du code ce qui aboutit à une collaboration plus efficace. En effet, ce qu'apporte gitlab par rapport à un simple serveur de partage de fichiers comme \textit{nfs} ou \textit{ftp}, c'est de pouvoir avoir une version sur sa propre machine, coder sur cette version locale et soumettre ses modifications au dépôt distant (gitlab) avec une gestion intelligente des conflits (quand plusieurs personnes modifient un même fichier au même endoit).
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Gitlab possède aussi une interface web qui permet de faire de la gestion de projet grâce à la section \textit{issue} et \textit{tableau}(cf. Figure~\ref{fig:gitlabBoard}). En effet, pour une tâche donnée, il fallait faire une \textit{issue} qui y correspondait. On peut voir une \textit{issue} comme un \textit{post it} qui peut être détaillé et commenté. Alors, chaque \textit{issue} était étiqueté par un ou plusieurs tags qui permettent d'identifier les différentes categories à laquelle correspondait la tâche. Parmi ces tags, on peut retrouver les tags: \textit{TODO}, \textit{IN PROGRESS} et \textit{DONE}. C'est là que la section tableau de gitlab intervient. En effet, cet outil permet de visualiser les \textit{issues} par tags. Si l'on met les 3 tags précédants en colonnes du tableau, alors, on simule un tableau \textit{scrum} et suit cette methode de travail.
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\centering
|
|
|
|
|
\caption{Capture d'écran du tableau de gitlab}
|
|
|
|
|
\includegraphics[width=\textwidth]{gitlabBoard}
|
|
|
|
|
\label{fig:gitlabBoard}
|
|
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
|
|
\subsection{Les données}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Les données sont réparties en plusieurs entités: le réseau, la station et le canal. Elle sont réparties de la manière suivante:
|
|
|
|
|
\begin{figure}[h]
|
|
|
|
|
\caption{Modèle du domaine de station}
|
|
|
|
|
\includegraphics[width=\textwidth]{stationDataModel}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\subsubsection{Le réseau}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Le \textit{Network} correspond à un moyen d'identifier la donnée. Un réseau est lui même identifié par un code alphanumérique de quelques caractères (exemple : 'FR'). Ainsi, pour des opérations faisant intervenir plusieurs pays différents, il est possible de décentraliser les données et de les retrouver facilement.
|
|
|
|
|
\subsubsection{La station}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Une \textit{Station} est une représentation abstaite du lieu où sont placés différents capteurs. Elle est aussi identifiée par un code alphanumérique (exemple: 'CFF'). Les stations sont réparties dans les différents réseaux en fonction du cadre de l'opération dont elle fait partie.
|
|
|
|
|
\subsubsection{Le canal}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Un \textit{Channel} correspond à un instrument d'une station sur une periode de temps. De ce fait, deux \textit{channels} différents peuvent avoir le même code (exemple: 'HHZ') mais cela veut dire qu'il y a eu une interruption humaine dans l'envoi de données. La fermeture puis réouverture d'un \textit{channel} ne doit pas être confondu avec un \textit{gap}, qui est une interuption de l'envoi de données à un moment où on s'attend à en recevoir.
|
|
|
|
|
\subsubsection{Le traitement de la donnée}
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\includegraphics[width=\textwidth]{organigrameNoeudANoeudB}
|
|
|
|
|
\caption{Parcours de la donnée depuis l'acquisition jusqu'à la distribution\cite{articleResif}}
|
|
|
|
|
\label{fig:parcourDonnee}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Comme on peut le voir sur la figure~\ref{fig:parcourDonnee}, la donnée récoltée par les stations RÉSIF est directement envoyée au \textit{noeud A} qui s'occupe de la valider. Une fois ce travail terminé, cette donnée est transmise au \textit{noeud B} qui a pour mission de la distribuer aux utilisateur\textperiodcentered ice\textperiodcentered s, notamment au Commissariat à l’Énergie Atomique (CEA) qui peut lancer des alertes aux populations en cas de données montrant un séisme dangereux. Pour palier à cette mission, le \textit{noeud B} met à disposition plusieus \textit{web services} pour tout\textperiodcentered se\textperiodcentered s.
|
|
|
|
|
|
|
|
|
|
\subsection{Les differents web services}
|
|
|
|
|
\subsubsection{Comment utiliser un web service ?}
|
|
|
|
|
\label{txt:explicationURL}
|
|
|
|
|
Durant mon stage, j'ai dû travailler sur différents \textit{web services}.
|
|
|
|
|
Chaque \textit{web service} est interrogeable via URL. L'URL est composée en différentes parties
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item \textit{le nom de domaine}: ws.resif.fr. Ce nom de domaine est variable selon le contexte. En effet, celui-ci est le nom de domaine pour le contexte de production. Il en existe d'autres pour d'autres contextes.
|
|
|
|
|
\item \textit{le chemin vers le web service}: /fdsnws/station/1/query. Ce chemin permet d'identifier le \textit{web service} que l'on veut interroger. Il est composé en 4 parties: la norme (fdsnws), le \textit{web service} (station), la version (1), et le mode d'interrogation (query).
|
|
|
|
|
\item \textit{les paramètres}: ?net=FR\&sta=CFF\&level=channel. Le début de la liste de paramètres doit commencer par un "?". Ensuite, chaque paramètre doit être séparé par un "\&". Enfin, la forme que prend la définition d'un paramètre est: $<$paramètre$>$=$<$valeur$>$
|
|
|
|
|
\end{itemize}
|
|
|
|
|
Ainsi une URL possible peut être \\
|
|
|
|
|
\href{https://ws.resif.fr/fdsnws/station/1/query?net=FR&sta=CFF&level=channel}{ws.resif.fr/fdsnws/station/1/query?net=FR\&sta=CFF\&level=channel}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour accéder aux données, il faut interroger le bon \textit{web service} avec une URL structurée. Voici les différents \textit{web services} que j'ai testé.
|
|
|
|
|
\subsubsection{Station}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Le \textit{web service} \textbf{\textit{\href{https://ws.resif.fr/fdsnws/station/1}{station}}} permet de récupérer les méta-données des stations de mesure. C'est à dire, leur nom, leur position, les cannaux disponibles, etc.. Bien qu'il soit possible de récupérer ces méta-données sous forme de texte, le principal format pour ce genre de requête est le StationXML, un dérivé du XML. Ce format permet un traitement numérique plus facile ainsi qu'une plus grande capacité à contenir des informations qu'un format texte habituel. Voici deux exemples de requêtes, \href{https://ws.resif.fr/fdsnws/station/1/query?net=FR&sta=CFF&cha=HHZ&level=channel&format=xml}{une sous le format XML} et \href{https://ws.resif.fr/fdsnws/station/1/query?net=FR&sta=CFF&cha=HHZ&level=channel&format=text}{la même requête sous le format text} (liens cliquables, cf. Figure~\ref{fig:URLstationXML}, Figure~\ref{fig:URLstationText} pour la version papier).
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Exemple d'une requête \textit{station} demandant du StationXML pour la station FR.CFF }
|
|
|
|
|
\includegraphics[width=\textwidth]{StationXMLExemple}
|
|
|
|
|
\label{fig:XMLex}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\subsubsection{Availability}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Le \textit{web service} \textbf{\textit{\href{https://ws.resif.fr/fdsnws/availability/1}{availability}}} permet aux chercheur\textperiodcentered euse\textperiodcentered s de pouvoir connaître les périodes dans lesquelles il y a des données étant donné des réseaux, des stations ou des canaux.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Ce \textit{web service} est décomposé en deux points d'entrée qui donnent des résultats différents car la nature de ce que l'on demande est différente. Dans le cas du point d'entrée \textit{query}, on veut savoir les plages temporelles \textbf{continue} disponibles. Pour le point d'entrée \textit{extent}, on demande aussi les plages temporelles disponibles à la différence près que les données qui sont dans la plage peuvent comporter des \textit{gaps}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Dans l'url, cela ce matérialisera par le changement de chemin vers le \textit{web service} (cf. explication de l'url \ref{txt:explicationURL}). En effet, les chemins ressembleront à cela:
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item \textit{fdsnws/availability/1/query} pour \textit{query}
|
|
|
|
|
\item \textit{fdnsws/availability/1/extent} pour \textit{extent}.
|
|
|
|
|
\end{itemize}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Voici des exemples de requêtes \href{https://ws.resif.fr/fdsnws/availability/1/extent?net=FR&sta=CFF&format=text}{au format text}, \href{https://ws.resif.fr/fdsnws/availability/1/extent?net=FR&sta=CFF&format=json}{json} et \href{https://ws.resif.fr/fdsnws/availability/1/extent?net=FR&sta=CFF&format=geocsv}{csv}(cf. Figure~\ref{fig:URLavailabilityText}, Figure~\ref{fig:URLavailabilityJson}, Figure~\ref{fig:URLavailabilityCsv} pour la version papier).
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Exemple d'une requête \textit{availability} demandant du texte pour la station FR.CFF }
|
|
|
|
|
\includegraphics[width=\textwidth]{availabilityEx}
|
|
|
|
|
\label{fig:AvaEx}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\subsubsection{Dataselect}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Le \textit{web service} \textbf{\textit{\href{https://ws.resif.fr/fdsnws/dataselect/1}{dataselect}}} permet de sélectionner des données en fonction des réseaux, stations et canaux sur une periode de temps. Le format de la réponse est un fichier binaire sous le format \textit{MiniSEED}. Il est donc nécessaire d'avoir un outil pour lire ce type de fichier.
|
|
|
|
|
\subsubsection{PH5}
|
|
|
|
|
Les \textit{web services} \textbf{\textit{\href{https://ph5ws.resif.fr/fdsnws/dataselect/1}{dataselect}}} et \textbf{\textit{\href{https://ph5ws.resif.fr/resifws/availability/1}{availability}}} ont aussi leur version en PH5. C'est à dire que ce sont des gros fichiers stockés sous le format PH5 et délivrés sous les formats disponibles mentionnés plus haut.
|
|
|
|
|
\subsection{Réflexion sur les sénarios}
|
|
|
|
|
\label{chap:scenarReflexion}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour établir un scénario, il me fallait prendre un temps de réflexion pour comprendre le \textit{web service} que je m'apprêtais à tester. Pour cela, j'ai pu avoir une approche pour cerner les cas intéressants.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Tout d'abord, je lisais la documentation des \textit{web services} pour bien comprendre leur utilité. Ensuite, je devais comprendre l'utilisation des paramètres qui permettent de restreindre la donnée. Une fois cette étape réalisée, je faisais varier les paramètres entre des valeurs normales, des valeurs improbables et des valeurs aux limites de ce que le \textit{web service} autorisait (par exemple, une latitude 181°).
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Ainsi, en combinant les paramètres, je créais des URL et les testais pour voir le comportement du \textit{web service}. C'est ici que se situait la princnipale difficulté dans le processus de réflexion. En effet, c'est dans ces moment là qu'il fallait déterminer si le \textit{web service} se comportait normalement. Aussi, il est possible que j'eu oublié des cas du fait de cette methode. Cependant, c'est la meilleure que j'ai pu trouver pour avoir des idées de scénarios.
|
|
|
|
|
|
|
|
|
|
\subsection{Écriture des scénarios}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour pouvoir tester le fonctionnement des differents \textit{web services}, j'ai du écrire des scénarios. Ceux-ci sont la traduction en mots de la période de réflexion expliquée plus haut (cf. Chapitre ~\ref{chap:scenarReflexion}). Ces scénarios sont décomposés en plusieurs éléments appelés \textit{steps}:
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item Le type de \textbf{scénario (outline/inline)} et son titre (ex. \textit{Scenario Outline:} S'abonner à des chaines Peertube)
|
|
|
|
|
\item \textbf{L'initialisation} du contexte en fonction du comportement souhaité (ex. \textit{Étant donné} que je suis connécté·e avec mon compte)
|
|
|
|
|
\item \textbf{Les actions} à tester (ex. \textit{Quand} je clique sur un bouton \textit{s'abonner})
|
|
|
|
|
\item \textbf{La description} du comportement attendu (ex. \textit{Je m'attend à} pouvoir voir mon abonnement dans la liste des abonnements et le boutton \textit{s'abonner} devenir \textit{se désabonner})
|
|
|
|
|
\item \textbf{Les exemples} de paramètres qui vont être testés si on est \textbf{dans un scénario outline} (ex. \textit{Par exemple}, si je m'abonne à 'Hygiene mental', à 'Politikon', à 'Tzitzimitl')
|
|
|
|
|
\end{itemize}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Le format du ficher de scénario permet d'utiliser un langage naturel quel qu'il soit. Cependant, il y a quand même des mots clefs qui sont écrits en anglais. J'ai donc rédigé les scénarios en anglais pour permettre une meilleure fuidité de lecture ainsi que pour internationaliser mes scénarios dans un contexte polylingue tel qu'au laboratoire ISTerre.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour ne pas répéter de code inutilement, j'essayais à chaque fois de réutiliser les mêmes \textit{steps}. C'est ainsi que dans tout mes scénarios, je réalise le même \textit{step}: \textit{When the web service is "GET|POST" requested}. En effet, ce \textit{step} me permet de faire une requête au \textit{web service} qui était paramétré. Ainsi, j'évite de faire un \textit{step} par \textit{web service}, ce qui facilite l'écriture de scénario pour le futur.
|
|
|
|
|
\subsubsection{Tags}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Dans behave, il existe une notion de tag qui permet d'étiqueter des scénarios. Ainsi, j'ai pu différencier plusieurs types de scénarios:
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item Ceux qui testent le code de retour de la requête: \textit{@HTTPStatus}
|
|
|
|
|
\item Ceux qui testent que le \textit{web service} retourne une réponse correcte (cas particulier du tag précédent (code de retour égale à 200)): \textit{@200}
|
|
|
|
|
\item Ceux qui testent le contenu de la requête: \textit{@content}
|
|
|
|
|
\item Ceux qui testent que le \textit{web service} est bien en état de marche: \textit{@healthcheck}
|
|
|
|
|
\item Ceux qui devraient passer mais qui ne passent pas: \textit{@failling}
|
|
|
|
|
\end{itemize}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Le tag \textit{@failling} met souvent en évidence un bug.
|
|
|
|
|
|
|
|
|
|
\subsection{Implémenation des tests}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour implementer mes tests, j'ai dû reprendre chaque \textit{step} du scénario (\textit{Given, When, Then, And, But}) et coder leurs sens. Par exemple, pour un \textit{Given}, la plupart du temps, je devais initialiser le contexte, pour les \textit{Then}, je devais comparer les résultats des \textit{When} avec ce qui était attendu. Aussi, toujours pour les mêmes raisons évoquées plus haut, le code est écrit en anglais.
|
|
|
|
|
\subsubsection{Exemples}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Voici un exemple de scénario qui illustre le travail depuis l'écriture de ce dernier, jusqu'à son implémentation.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Sur la figure~\ref{fig:scenarioLatitudeFeature}, on demande à \textit{behave} d'exécuter trois \textit{steps} différents: un pour initialiser le paramètre \textit{latitude} avec la valeur \textit{-100} (la latitude minimale sur Terre est de -90°, au dela, les coordonnées décrivent un point dans l'espace), un pour transmettre la requête au \textit{web service} et enfin, un pour vérifier que le code de retour du \textit{web service} est bien égale à 400 (le code 400 signifie que l'utilisateur\textperiodcentered ice a fait une erreur dans sa requête).
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Exemple d'un scénario}
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
Scenario: Latitude inférieur à -90°
|
|
|
|
|
Given une 'latitude' de '-100'
|
|
|
|
|
When le web service est intérogé via une URL
|
|
|
|
|
Then le code de retour du web service doit être '400'
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
\label{fig:scenarioLatitudeFeature}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Au niveau du code, l'implémentation des \textit{steps} ressemble à la figure~\ref{fig:implementationScenario}
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Implémentation du scénario (pseudo code)}
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
@given("une '{paramètre}' de '{valeur}'")
|
|
|
|
|
fonction initaliser un paramètre:
|
|
|
|
|
ajouter aux paramètres de la requête 'paramètre' égale à 'valeur'
|
|
|
|
|
|
|
|
|
|
@when("le web service est interogé via une URL")
|
|
|
|
|
fonction faire une requête au web service:
|
|
|
|
|
url <= construire l'URL avec les paramètres initalisés avant
|
|
|
|
|
réponse <= interroger le web service
|
|
|
|
|
|
|
|
|
|
@then("le code de retour du web service doit être '{code}'")
|
|
|
|
|
fonction comparer le code de retour:
|
|
|
|
|
si le code de retour de réponse est différent de 'code':
|
|
|
|
|
dire à behave que le test a échoué
|
|
|
|
|
sinon
|
|
|
|
|
ne rien faire car tout se passe bien
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
\label{fig:implementationScenario}
|
|
|
|
|
\end{figure}
|
|
|
|
|
Pour chaque \textit{step}, \textit{behave} ira chercher et exécuter la bonne fonction grâce au préfixe \textit{@given}, \textit{@when} et \textit{@then}. Ainsi, le nom de la fonction n'est pas important pour \textit{behave}. Les variables peuvent être transmises de fonction en fonction grâce à la notion de \textit{context}. Concrètement, c'est un objet qui est passé en paramètre de chaque fonction et qui est capable de stocker des variables sous la forme de propriétés.
|
|
|
|
|
\subsubsection{Détail d'un step}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
La complexité d'un step peut varier en fonction de sa nature. En effet, les steps \textit{given} sont assez simples à implémenter (cf. Figure.~\ref{fig:given}). Les autres \textit{steps} sont en général plus complexes.
|
|
|
|
|
\begin{figure}
|
|
|
|
|
\caption{Implementation d'un \textit{step} given}
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
@given("the '{parameter}' of '{value}'")
|
|
|
|
|
def setURL(context, parameter, value):
|
|
|
|
|
context.commonArgs[parameter] = value
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
\label{fig:given}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Par exemple, le \textit{step} "\textit{When the web service is 'GET|POST' requested}" (cf. Figure~\ref{fig:when}) a su poser problème lors de son implémentation.
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Implementation d'un \textit{step} when}
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
@when('the webservice is "{methods}" requested')
|
|
|
|
|
def requestWebService(context, methods):
|
|
|
|
|
"""
|
|
|
|
|
Make and submit queries parametered by given steps
|
|
|
|
|
"""
|
|
|
|
|
methods = methods.split('|') #= ['GET'] or ['POST'] or ['GET', 'POST']
|
|
|
|
|
|
|
|
|
|
# Merge args form commons args and args that are specifics to the first query
|
|
|
|
|
args = [ context.commonArgs | spe for spe in context.specificArgs.values()] if len(context.specificArgs) > 0 else [context.commonArgs]
|
|
|
|
|
context.queries = [[] for i in range(len(args)*len(methods))]
|
|
|
|
|
qg = QueryGenerator()
|
|
|
|
|
raiseError = None
|
|
|
|
|
i=0
|
|
|
|
|
|
|
|
|
|
#Number of args lines match with number of request
|
|
|
|
|
for request in args:
|
|
|
|
|
args = context.commonArgs | context.specificArgs
|
|
|
|
|
for method in methods:
|
|
|
|
|
context.queries[i] = qg.generateQuery(context.ws, request, context.headerOnly, refreshCache=context.refreshCache, login=context.queryAuthLoggin, password=context.queryAuthPassword)
|
|
|
|
|
try:
|
|
|
|
|
if method.upper() == 'GET':
|
|
|
|
|
context.queries[i].get()
|
|
|
|
|
elif method.upper() == 'POST':
|
|
|
|
|
context.queries[i].post()
|
|
|
|
|
else:
|
|
|
|
|
raise ValueError(f"{method} is not a suported method")
|
|
|
|
|
|
|
|
|
|
# custome the Traceback
|
|
|
|
|
except ConnectionError:
|
|
|
|
|
raiseError = ValueError(f"Can not connect to {context.ws}")
|
|
|
|
|
except InvalidSchema:
|
|
|
|
|
raiseError = ValueError(f"The URL is not valide: {context.ws}")
|
|
|
|
|
if raiseError: # and raise if raiseError != None
|
|
|
|
|
raise raiseError
|
|
|
|
|
|
|
|
|
|
i+=1
|
|
|
|
|
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
\label{fig:when}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Je vais maintenant décrire son fonctionnement. Dans un premier lieu, je sélectionne les méthodes d'intérrogations du \textit{web service} défini dans le scénario. Il est possible de faire un requête POST, une requête GET ou les deux. En suite, j'initie des variables pour les utiliser plus tard. Cependant, à ce moment là, la variable \textit{args} sert juste à initaliser la propriété (sorte de variable) \textit{context.queries}. Ensuite, on rentre dans une boucle \textit{for}, qui va permettre de lancer autant de requêtes au \textit{web service} qu'il y en a de définies dans le contexte. Une requête est modélisée dans le contexte par une liste de dictionaires d'arguments. Par exemple, la liste [{net: FR, sta: CIEL}, {net: FR, sta: CFF}] possède deux requêtes. Ainsi, il est possible de forger plusieurs requêtes dans les steps \textit{given}. Ainsi, chaque requêtes est envoyée autant de fois qu'il y a de méthodes HTTP demendées par le step. Par exemple, si on demande du GET et du POST, mon programe interrogera quatres fois le \textit{web service} si l'on reprend l'exemple précédent. C'est la raison d'être de la deuxieme boucle \textit{for}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Je vais maintenant détailler le contenu des boucles \textit{for}. Donc, pour chaque requête, je crée un objet \textit{Query} (cf. Chapitre~\ref{chap:modelDeClasse}) grâce à un générateur de \textit{Query}. L'objet \textit{Query} est stocké dans le contexte dans une liste. Ainsi, en fonction de la méthode HTTP, la methode de \textit{Query} \textit{get} ou \textit{post} est appelée.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
À la fin de la boucle, il y a donc un liste de \textit{Query} dans le contexte. Aussi, chaque \textit{Query} possède un objet \textit{Response}. Enfin, le test échoue si la méthode demendée n'existe pas, si le \textit{web service} n'est pas joignable ou si l'URL est mal écrite.
|
|
|
|
|
\subsection{Environnement}
|
|
|
|
|
\subsubsection{Environnement behave}
|
|
|
|
|
\textit{Behave} est capable de générer un environnement entre chacun des \textit{items} composant les tests (\textit{feature}, \textit{scénario}, \textit{tag}, \dots). Pour cela, il faut définir des fonctions avec des noms prédéfinis par \textit{behave} dans un fichier nommé \textit{environment.py}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Les noms des fonctions sont composés de la manière suivante: $<$before/after$>$\_$<$\textit{element}$>$ (exemple: before\_feature, after\_scenario, before\_all, \dots). J'ai pu me servir de certaines de ces fonctions, notamment pour la configuration des tests par des éléments externes tel que des variables d'environnements ou des fichiers de configuration. Ainsi, avant tout, je configure le protocole utilisé (http ou https) et le couple loggin/mot de passe pour l'accès aux données réstreintes. Avant chaque \textit{feature}, je sélectionne le \textit{web service} adéquat.
|
|
|
|
|
\subsubsection{Configuration par l'environnement}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour plus de souplesse à l'utilisation, j'ai fait en sorte que les tests soient configurables sans que le code source soit modifié. En effet, il existe plusieurs contextes de déploiment pour les différent \textit{web services}: le contexte de production, celui de développement et celui de stage. Chaque contexte a son utilité et est accessible par un nom de domaines (début de l'URL) différent. Ainsi, pour définir le contexte depuis l'extérieur du programme, il suffit de définir la vairable d'environement \textit{BEHAVE\_TEST\_CONTEXT} avec les valeurs \textit{PROD}, \textit{DEV} ou \textit{STAGING}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Les URL sont ensuite récupérées depuis un fichier de configuration au format YAML. Ces URL contiennent à la fois le contexte (ws.resif.fr, ws-dev.resif.fr et ws-staging.resif.fr) ainsi que le chemin vers chaque \textit{web service}. En effet, celui-ci est variable en fonction du contexte. Par exemple pour ph5-availability, les URL sont: \textit{ph5ws.resif.fr/resifws/availability/1/query}, \textit{ws-dev.resif.fr/resifws/ph5-availability/1/query} et \textit{ph5ws-staging.resif.fr/resifws/availability/1/query}. La hiérarchie des informations du fichier fait qu'il est facile de modifier ou ajouter des URL. En effet, le premier niveau de hiérarchisation est le nom du \textit{web service} et le deuxième, le nom du contexte (cf. Figure~\ref{fig:yamlOK}). C'est ici que ce situe l'URL. Ainsi, pour ajouter un \textit{web service} dans la configuration, il sufit d'ajouter son nom et de décrire chaque contexte. Si cette hierarchie était inversée (cf Figure~\ref{fig:yamlKO}), il serait plus compliqué de retrouver les informations. Imaginons que je veuille modifier les URL \textit{web service} \textit{station}. Pour cela, il faudrait que je prenne chaque contexte et que je trouve parmi tous les \textit{web services} le bon, le modifier et répéter l'opération autant de fois qu'il y a de contexte.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Ainsi, j'ai pu faire en sorte que la personnalisation des tests soit maximale grâce aux variables d'environnements. En effet, il y a quatre variables d'environnemnts avec lesquelles il est possible de spécialiser les tests:
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item \textbf{BEHAVE\_TEST\_PROTOCOLE}: pour définir le protocole utilisé: http ou https (https par défaut)
|
|
|
|
|
\item \textbf{BEHAVE\_TEST\_CONTEXT}: pour définir le contexte (PROD par défaut)
|
|
|
|
|
\item \textbf{BEHAVE\_TEST\_LOGGIN}: pour définir l'utilisateur\textperiodcentered ice et ainsi garantir le respect des droits vis-à-vis de la visibilité des données (rien par defaut)
|
|
|
|
|
\item \textbf{BEHAVE\_TEST\_PASSWORD}: pour authentifier l'utilisateur\textperiodcentered ice (rien par défaut)
|
|
|
|
|
\end{itemize}
|
|
|
|
|
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Extrait du fichier de configuration des contextes}
|
|
|
|
|
\label{fig:yamlOK}
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
dataselect:
|
|
|
|
|
production: 'ws.resif.fr/fdsnws/dataselect/1/query'
|
|
|
|
|
developement : 'ws-dev.resif.fr/fdsnws/dataselect/1/query'
|
|
|
|
|
staging: 'ws-staging.resif.fr/fdsnws/dataselect/1/query'
|
|
|
|
|
|
|
|
|
|
availability:
|
|
|
|
|
production: 'ws.resif.fr/fdsnws/availability/1/query'
|
|
|
|
|
developement : 'ws-dev.resif.fr/fdsnws/availability/1/query'
|
|
|
|
|
staging: 'ws-staging.resif.fr/fdsnws/availability/1/query'
|
|
|
|
|
|
|
|
|
|
ph5-dataselect:
|
|
|
|
|
production: 'ph5ws.resif.fr/fdsnws/dataselect/1/query'
|
|
|
|
|
developement : 'ws-dev.resif.fr/fdsnws/ph5-dataselect/1/query'
|
|
|
|
|
staging: 'ph5ws-staging.resif.fr/fdsnws/dataselect/1/query'
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
|
|
\begin{figure}
|
|
|
|
|
\caption{Configuration avec une hiérarchie invérsée}
|
|
|
|
|
\label{fig:yamlKO}
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
production:
|
|
|
|
|
dataselect: 'ws.resif.fr/fdsnws/dataselect/1/query'
|
|
|
|
|
availability: 'ws.resif.fr/fdsnws/availability/1/query'
|
|
|
|
|
ph5-dataselect: 'ph5ws.resif.fr/fdsnws/dataselect/1/query'
|
|
|
|
|
devlopement:
|
|
|
|
|
availability: 'ws-dev.resif.fr/fdsnws/availability/1/query'
|
|
|
|
|
dataselect: 'ws-dev.resif.fr/fdsnws/dataselect/1/query'
|
|
|
|
|
ph5-dataselect: 'ws-dev.resif.fr/fdsnws/ph5-dataselect/1/query'
|
|
|
|
|
staging:
|
|
|
|
|
ph5-dataselect: 'ph5ws-staging.resif.fr/fdsnws/dataselect/1/query'
|
|
|
|
|
dataselect: 'ws-staging.resif.fr/fdsnws/dataselect/1/query'
|
|
|
|
|
availability: 'ws-staging.resif.fr/fdsnws/availability/1/query'
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\subsection{Conception}
|
|
|
|
|
\subsubsection{Démarche}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour implémenter les \textit{steps}, ma démarche était empirique. C'est à dire que je l'implémentais, vérifiais son comportement et l'améliorais ensuite. Ainsi, j'étais dans l'esprit de la methode \textit{agile}. En effet, avec les tickets gitlab, je pouvais facilement avoir une tache pour reprendre un code précédemment écrit.
|
|
|
|
|
|
|
|
|
|
\subsubsection{Factorisation de code}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
C'est dans cet esprit que, lors de la réalisation des tests du deuxième web service, \textit{availability}, je commençais à reprendre des fonctionalités du premier, \textit{station}, comme l'envoi de requête au \textit{web service} ou la verification de format de la réponse. À ce moment là, j'ai ressenti le besoin de mettre en commun certaines parties de code et d'en spécialiser d'autres. Ainsi, j'ai commencé un travail de refactorisation de code qui à depuis toujours était présent jusqu'à la fin de mon stage.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
En effet, dupliquer du code, c'est pouvoir introduire le même bug à plusieurs endroits différents ou bien même une impossibilité de reprendre le code par une autre personne car ce genre de code est assez difficile à lire et comprendre. Refactoriser le code permet donc une meilleure stabilité ainsi qu'une plus grande facilité à le corriger.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour éviter de dupliquer du code, j'ai dû créer differentes classes ayant différrents types de relation entre elles (associations dirigées, héritages, \dots). Une des difficutltés non négligable est qu'en \textit{python}, le principe de classe abstraite ou d'interface n'existe pas. Cela m'a notamment posé problème lors de l'implémentation des sous-classes de \textit{Query}. En effet, le comportement des sous classes dépendait de plusieurs paramètres: la méthode HTTP (GET ou POST) et le \textit{web service} intérrogé. Ainsi, un objet \textit{Query} n'a pas de sens s'il est instancié.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Le fait d'avoir des classes abstraites ou des interfaces permet aussi de créer ce qu'on appelle des points d'extensions. Un point d'extension, c'est une entité qui permet de garantir des fonctionnalités lorsequ'une classe hérite de cette entité. Par exemple, si j'hérite d'une interface \textit{Conteneur}, les classes qui l'implémentent, comme \textit{Liste}, \textit{Fille} ou \textit{Queue}, sont obligées de pouvoir contenir des données. Ainsi, la personne qui utilise ces classes n'a pas à se demander si elle peut contenir des données.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour palier à ce problème, j'ai simulé le comportement d'une classe abstraite grâce à la valeur \textit{NotImplemeted}. Cette valeur est retournée à chaque fois qu'une méthode censée être abstraite est appelée. Toute fois, je n'ai pas interdit l'instanciation de ces objets car cela complexifirait le code, simplement pour introduire une notion étrangère à \textit{python}. Ainsi, j'ai pu obtenir plusieurs points d'extensiblilités (Query, Response, Validator, \dots), ce qui permettra une maintenabilité plus simple pour les développeur\textperiodcentered euse\textperiodcentered s qui seront suceptibles de reprendre mon code. Ainsi, pour permettre au modèle de pouvoir tester de nouveaux \textit{web services}, il suffit de créer une nouvelle classe qui hérite de \textit{Query} et une nouvelle classe qui hérite de \textit{Response} et implementer les méthodes \textit{abstraites} (cf. Figure~\ref{fig:QueryClassDiag}, Figure~\ref{fig:ResponseClassDiag}).
|
|
|
|
|
\subsubsection{Déscription du modèle de classes}
|
|
|
|
|
\label{chap:modelDeClasse}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Dans mon modèle de classes, j'ai pu faire un point d'entrée qui permet une simple utilisiation depuis l'éxterieur, dans mon cas, depuis les tests \textit{behave}. En effet, la classe \textit{QeryGenerator} agit comme une \textit{factory}, c'est-à-dire, une classe qui permet de créer d'autre types de classes en fonction de divers paramètres. Par exemple ici, \textit{QueryGenerator} va créer des classes filles de \textit{Query} en fonction du \textit{web service} que l'on veut interroger grâce à une méthode nommée \textit{generateQuery}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
La classe \textit{Query} modélise une requête à passer ou passée à un \textit{web service}. Une \textit{Query} est capable de construire la requête en fonction de la méthode d'interrogation (GET ou POST). Une fois que les requêtes étaient construites, il était possible d'interroger le serveur dont l'URL et les arguments sont attributs de \textit{Query}(cf. Figure~\ref{fig:ValidatorClassDiag}).
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Cependant, une requête doit être spécialisée en fonction du \textit{web service} interogé (cf. Figure~\ref{fig:QueryClassDiag}). Cela permet de spécialiser le comportement de la réponse lors de sa création dans la méthode \textit{buildResponse}. Par exemple, pour le \textit{web service} \textit{station}, il a fallu créer une classe \textit{StationQuery} qui implémente la méthode abstraite de \textit{Query} nommé \textit{buildResponse} qui est appelée lors ce qu'on intrérroge le \textit{web service} et que l'on a une réponse. La structure de ce genre de méthode est décrite sur la figure~\ref{fig:buildResponse}.
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Structure de la méthode \textit{buildResponse}}
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
class StationQuery
|
|
|
|
|
methode buildResponse(reponseBrute):
|
|
|
|
|
si le format est xml, alors
|
|
|
|
|
réponse <= créerUneReponseStationQuiTraiteDuXML(reponseBrute)
|
|
|
|
|
sinon si le format est text, alors
|
|
|
|
|
réponse <= créerUneReponseStationQuiTraiteDuText(reponseBrute)
|
|
|
|
|
sinon
|
|
|
|
|
réponse <= créerUneReponseStationQuiNeFaitQueStoker(reponseBrute)
|
|
|
|
|
fin si
|
|
|
|
|
fin methode
|
|
|
|
|
fin classe
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
\label{fig:buildResponse}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Diagramme de classe pour les classes \textit{Query}}
|
|
|
|
|
\includegraphics[width=\textwidth]{query}
|
|
|
|
|
\label{fig:QueryClassDiag}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
La classe \textit{Response} est aussi un point d'extensibilité qui garantit qu'une réponse sait dire si son contenu est bien formaté. Les classes qui héritent directement de \textit{Response} sont aussi des classes abstraites. Elles permettent de spécialiser le comportement des classes filles en fonction des \textit{web services} interrogés. Par exemple, il existe une classe abstraite \textit{ResponseAvailability}. C'est à l'étage du dessous que sont implémentées les classes concrètes qui permettent de traiter un format (par exemple la classe \textit{ResponseDataselectMiniSeed}). Ce découpage est ainsi fait car deux \textit{web services} peuvent renvoyer un même format mais avec un contenu complétement différent. Par exemple, \textit{availability} peut renvoyer des valeurs au format \textit{text} (les valeurs son séparées par des espaces) ainsi que \textit{station} (les valeurs sont séparées par un pipe) (cf. Figure~\ref{fig:respAvaText}, Figure \ref{fig:respStaText}). Ainsi, le traitement de la réponse est différente et c'est pour répondre à cette contrainte que j'ai dû faire une si grosse arborescence(cf. Figure~\ref{fig:ResponseClassDiag}).
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Extrait de réponse au format \textit{text} de \textit{availability}}
|
|
|
|
|
\begin{scriptsize}
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
#Network Station Location Channel Quality SampleRate Earliest Latest Updated TimeSpans Restriction
|
|
|
|
|
FR CFF 00 BHE D 20.0 2022-05-27T00:00:05.100000Z 2022-06-02T07:26:12.200000Z 2022-06-02T07:11:59Z 2 OPEN
|
|
|
|
|
FR CFF 00 BHE M 20.0 2015-05-22T10:49:42.350000Z 2022-05-27T00:00:05.050000Z 2022-06-02T03:45:01Z 325 OPEN
|
|
|
|
|
FR CFF 00 BHZ D 20.0 2022-05-27T00:00:00.950000Z 2022-06-02T07:25:54.200000Z 2022-06-02T07:11:59Z 2 OPEN
|
|
|
|
|
FR CFF 00 BHZ M 20.0 2015-05-22T10:49:42.350000Z 2022-05-27T00:00:00.900000Z 2022-06-02T03:45:01Z 297 OPEN
|
|
|
|
|
FR CFF 00 HHN M 100.0 2015-05-23T00:00:01.280000Z 2022-05-27T00:00:02.090000Z 2022-06-02T03:45:01Z 341 OPEN
|
|
|
|
|
FR CFF 00 HHN M 125.0 2010-01-01T00:00:00.316800Z 2015-05-22T08:09:20.224400Z 2020-03-09T09:50:57Z 2351 OPEN
|
|
|
|
|
FR CFF 00 HHZ M 125.0 2010-01-01T00:00:00.316800Z 2015-05-22T08:09:20.224400Z 2020-03-09T09:50:57Z 2339 OPEN
|
|
|
|
|
FR CFF 00 LHZ D 1.0 2022-05-27T00:03:07.000000Z 2022-06-02T07:22:30.000000Z 2022-06-02T07:11:59Z 1 OPEN
|
|
|
|
|
FR CFF 00 LHZ M 1.0 2015-05-22T10:49:29.000001Z 2022-05-27T00:03:06.000000Z 2022-06-02T03:45:01Z 293 OPEN
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
\end{scriptsize}
|
|
|
|
|
\label{fig:respAvaText}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Extrait de réponse au format \textit{text} de \textit{station}}
|
|
|
|
|
\begin{scriptsize}
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
FR|CFF|00|HHE|45.763000|3.111110|400.0|3.4|90.0|0.0|6.166106e+08|1|m/s|125|2008-09-09T00:00:00|2015-05-22T08:30:00
|
|
|
|
|
FR|CFF|00|HHN|45.763000|3.111110|400.0|3.4|0.0|0.0|6.166106e+08|1|m/s|125|2008-09-09T00:00:00|2015-05-22T08:30:00
|
|
|
|
|
FR|CFF|00|HHZ|45.763000|3.111110|400.0|3.4|0.0|-90.0|6.166106e+08|1|m/s|125|2008-09-09T00:00:00|2015-05-22T08:30:00
|
|
|
|
|
FR|CFF|00|BHN|45.763000|3.111110|400.0|3.4|0.0|0.0|6.291456e+08|1|m/s|20|2015-05-22T09:30:00|2500-12-31T23:59:59
|
|
|
|
|
FR|CFF|00|BHZ|45.763000|3.111110|400.0|3.4|0.0|-90.0|6.291456e+08|1|m/s|20|2015-05-22T09:30:00|2500-12-31T23:59:59
|
|
|
|
|
FR|CFF|00|HHE|45.763000|3.111110|400.0|3.4|90.0|0.0|6.291456e+08|1|m/s|100|2015-05-22T09:30:00|2500-12-31T23:59:59
|
|
|
|
|
FR|CFF|00|HHN|45.763000|3.111110|400.0|3.4|0.0|0.0|6.291456e+08|1|m/s|100|2015-05-22T09:30:00|2500-12-31T23:59:59
|
|
|
|
|
FR|CFF|00|LHN|45.763000|3.111110|400.0|3.4|0.0|0.0|6.291456e+08|1|m/s|1|2015-05-22T09:30:00|2500-12-31T23:59:59
|
|
|
|
|
FR|CFF|00|LHZ|45.763000|3.111110|400.0|3.4|0.0|-90.0|6.291456e+08|1|m/s|1|2015-05-22T09:30:00|2500-12-31T23:59:59
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
\end{scriptsize}
|
|
|
|
|
\label{fig:respStaText}
|
|
|
|
|
\end{figure}
|
|
|
|
|
Dans le paragraphe précédent, j'ai dit qu'un objet \textit{Response} devait être capable de vérifier si le format de son contenu était correct sans en expliquer les détails. C'est ce que vais donc faire ici. Pour pouvoir faire ça, la classe \textit{Response} doit utiliser un \textit{Validator}. C'est une classe qui permet de dire si une condition complexe est respéctée. Il existe deux sortes de validateurs pour le moment: les \textit{HTTPValidator} et les \textit{FormatValidator}. Ici ce sont des \textit{FormatValidator} qui sont utilisés par les objets \textit{Response}. Chaque format possède sa manière d'être vérifié. Par exemple, pour un format CSV, il faut vérifier que chaque ligne correspond au pattern "valeur séparateur" grâce à une expression régulière. J'avais essayé de faire cette verification avec la bibliothèque CSV mais l'objet qui permet de lire un CSV ne lève pas d'erreur lors ce que le contenu n'est pas bien formaté. Pour continuer l'exemple, le format \textit{MiniSEED} peut être lu grâce à la bibliothèque \textit{obspy}\cite{obspy}. Ainsi, si l'objet qui lit le contenu lève une erreur lors de la lecture du contenu, c'est qu'il est mal formaté. Cependant, il y a des formats particuliers comme le format ZIP qui en fait contient un fichier CSV à l'interieur. C'est pour ça que je l'ai fait hériter de CSV. Ansi, la méthode \textit{validate} de \textit{ZipValidator} extrait le fichier CSV à l'interieur et appelle ensuite la même méthode de son parent avec le contenu du fichier(cf. Figure~\ref{fig:ValidatorClassDiag}).
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Diagramme de classe pour les classes \textit{Validator}}
|
|
|
|
|
\includegraphics[scale=0.5]{validator}
|
|
|
|
|
\label{fig:ValidatorClassDiag}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\subsubsection{Transmission du savoir}
|
|
|
|
|
\paragraph{Documentation de ma production}
|
|
|
|
|
Pour pouvoir avoir une vision globale du projet ainsi que pour la transmission de ma production, j'ai dû la documenter. Pour cela, j'ai utilisé plusieurs outils. Tout d'abord, pour avoir une documentation de mon code en lui même, expliquer le rôle de chaque classe, chaque methode, j'ai utilisé l'outil \textit{pydoc}, qui permet de générer une documentation HTML en lisant les \textit{docstings} de mon code. Une \textit{docstring} est une sorte de paragraphe, placé en haut de l'item à documenter (classe, methode, \dots) expliquant l'utilité et le fonctionement de ce dernier. Cependant, je n'ai pas commencer à documenter mon code dès le début de sa production, j'ai donc pris une journée pour l'écrire, à la fin de l'implémentation des tests sur le deuxieme \textit{web service} que j'ai traité, c'est-à-dire, vers le début du mois de mai.
|
|
|
|
|
\begin{figure}
|
|
|
|
|
\caption{Extrais de la classe \textit{Query} comportent des docstrings}
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
class Query:
|
|
|
|
|
"""
|
|
|
|
|
Abstract class representing a Query sent to ws.resif.fr
|
|
|
|
|
|
|
|
|
|
Attributes:
|
|
|
|
|
args (dict): argument for the request (ex.: {'network': 'FR', 'start': '2020-12-12'})
|
|
|
|
|
refreshCache (bool): is the cach refreshed ?
|
|
|
|
|
response (Response): response of the web service
|
|
|
|
|
getUrl (str): complete URL if the method id GET
|
|
|
|
|
postBody (str): body of the post request
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
"""
|
|
|
|
|
Send a GET request and build the response
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Response: the response of the GET request
|
|
|
|
|
"""
|
|
|
|
|
response = requests.get(self.ws, params=self.args, headers=self._header, auth=requests.auth.HTTPDigestAuth(self.__digestTuple[0], self.__digestTuple[1])) if not self.headerOnly else requests.head(self.getUrl, auth=requests.auth.HTTPDigestAuth(self.__digestTuple[0], self.__digestTuple[1]))
|
|
|
|
|
self.buildResponse(response)
|
|
|
|
|
return self.response
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\subparagraph{}
|
|
|
|
|
Pour donner une explication sur les relations entres les classes, j'ai réalisé plusieurs diagrammes de classes avec l'outil \textit{plantuml}. Cette outil permet de générer un diagramme UML à partir d'un fichier texte formaté qui décrit les relations entre classes (cf. Figure~\ref{fig:plantuml}). L'avantage d'un tel outil est qu'il est facile à versionner par rapport à un fichier binaire. En effet, si il y a un conflit entre deux versions du dépôt, il sera difficile à résoudre si c'est un fichier binnaire car illisible. Pour résoudre un conflit, il faut fusionner à la main le contenu des fichiers. J'ai donc commencé la réalisation du fichier plantuml dès que j'ai eu plus d'une classe à implémenter.
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Extrait de fichier plantuml}
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
abstract class Query {
|
|
|
|
|
buildGetUrl()
|
|
|
|
|
{abstract} buildResponse(response)
|
|
|
|
|
refreshCache
|
|
|
|
|
response
|
|
|
|
|
pstBody
|
|
|
|
|
}
|
|
|
|
|
class AvailabilityQuery { buildResponse(response) }
|
|
|
|
|
class StationQuery {buildResponse(response) }
|
|
|
|
|
class DataselectQuery { buildResponse(response) }
|
|
|
|
|
class DataselectPh5Query { buildResponse(response) }
|
|
|
|
|
|
|
|
|
|
Query -> Response
|
|
|
|
|
Query <|-- StationQuery
|
|
|
|
|
Query <|-- AvailabilityQuery
|
|
|
|
|
Query <|-- DataselectQuery
|
|
|
|
|
Query <|-- DataselectPh5Query
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
\label{fig:plantuml}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\paragraph{Réunions}
|
|
|
|
|
À mi-chemin de mon stage, j'ai réalisé une présentation de mon travail dans le cadre d'une transmission de savoir au reste de l'équipe. Suite à cela, il y eu de nouveaux échanges et cela a permis d'enrichir le contenu de mes tests. En effet, ces échanges ont permis de déffinir un plan d'action pour les semaines qui ont suivi ainsi que mettre en lumière de nouveaux scénarios tel que la cohérence des \textit{web services} entres eux.
|
|
|
|
|
\subsubsection{Problèmes rencontrés}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Une des principales dificultés que j'ai pu rencontrer lors de ce stage est le comportement de \textit{behave}. En effet, quand on exécute un scenario, \textit{behave} va le faire échouer seulement si une exception est levée, c'est à dire, qu'une erreur a été rencontrée ou qu'un test de nature spécifique (assertion) n'est pas passé. Aussi, certains tests peuvent passer sans que le \textit{web service} ce soit comporté comme souhaité.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Par exemple, si je veux tester un code de retour HTTP égale à 400 en voulant tester un paramètre, ce code peut être renvoyé à cause d'un autre paramètre défectueux. Ainsi, le test passra mais n'aura pas validé le comportement attendu. Un autre exemple est quand par exemple je devais tester que le format texte était cohérent avec le format XML. Ici, j'avais un problème de code qui faisait que les deux requêtes que je faisait étaient identiques et donc, les résultats étaient eux aussi identiques (tous les deux au format XML) et je ne l'ai remarqué que lorseque je l'ai vu dans le code par hasard car \textit{behave} ne s'en rendait pas compte (cf. Figure~\ref{fig:behaveOK}).
|
|
|
|
|
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour palier à ce problème, à la fin de chaque implémentation, je verifiais à la main que le test passé corespond bien au comportement souhaité grâce à l'argument no-capture (cf. Figure~\ref{fig:behaveNoCapture}). Mais la limite de cette méthode est que, si il y a une régression dans le code, les tests qui fonctionnaient correctement avant peuvent ne plus fonctionner après.
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\centering
|
|
|
|
|
\caption{Capture d'écran du test d'équivalence entre le format XML et texte}
|
|
|
|
|
\includegraphics[width=\textwidth]{behaveOK}
|
|
|
|
|
\label{fig:behaveOK}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\centering
|
|
|
|
|
\caption{Capture d'écran du test d'équivalence entre le format XML et texte avec l'argument no-capture}
|
|
|
|
|
\includegraphics[width=\textwidth]{behaveNC}
|
|
|
|
|
\label{fig:behaveNoCapture}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\subsection{Au-delà du stage}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Tout au long de mon stage, je devais avoir à l'esprit que mon code serait repris et que le logiciel produit devra être utilisé le plus simplement possible.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Ainsi, j'ai pu penser à des améliorations telles que la mise en cache de certaines requêtes pour accélérer les tests, l'écriture d'un script permettant de simplifier le lancement des tests, un modèle de classes qui permet une génericité maximale. Certaines de ces idées ont dû être écartées par manque de temps et du fait de le trop grande complexité par rapport au contexte. C'est donc un piste pour continuer l'implémentation des tests.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
J'ai donc réalisé une documentation sur l'utilisation de ma production. Pour qu'elle soit facilement accessible et lisible, je l'ai faite en \textit{markdown}, un langage de mise en forme de texte, et l'ai mise dans le fichier \textit{REEDME.md}. Ce fichier est affiché automatiquement par gitlab dans l'onglet \textit{Files} (cf. Figure\ref{fig:reedme}).
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Section \textit{files} de gitlab}
|
|
|
|
|
\includegraphics[width=\textwidth, frame]{gitlabReedme}
|
|
|
|
|
\label{fig:reedme}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Pour que l'utilisateur\textperiodcentered ice des tests puisse facilement voir ce qui ce passe lors ce qu'un test échoue, j'ai travaillé la sortie standard (cf. Figure~\ref{fig:behaveKO}) des ces derniers (grossièrement ce qu'ils écrivent sur la console). En effet, le comportement de \textit{behave} est d'afficher les éléments que j'écris dans la sortie standard seuelment si un \textit{step} échoue. Ainsi, j'ai détaillé à chaque requête effecuée, l'URL (pour GET) et le corps de cette requête (pour POST) pour pouvoir la reproduire en dehors de mes tests. J'affiche aussi le loggin utilisé s'il a été configuré. Aussi, en fonction des \textit{steps} effectués, il peut y avoir des sorties différentes. Par exemple, pour le step \textit{Then the HTTP code returned must be 'code'}, le code d'erreur est écrit dans la sortie standard.
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Test qui a échoué}
|
|
|
|
|
\includegraphics[width=\textwidth, frame]{behaveKO}
|
|
|
|
|
\label{fig:behaveKO}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\subsection{En dehors du sujet}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
A diverses occasions j'ai pu participer à des activités organisées avec l'équipe RÉSIF-DC. Ainsi, j'ai pu assister à une réunion du commité technique de RÉSIF-SI(\textit{comtec}). Ces réunions ont pour but de se mettre d'accord entre différents laboratoires au niveau des problèmes techniques communs entre ces instances. Par exemple, si une information n'était pas délivrée et qu'il a été jugée nécessaire de l'introduire dans les réponses d'un \textit{web service}, le \textit{comtec} décide de la manière de le faire.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
J'ai aussi pu participer à une réunion \textit{créativité} avec les membres de l'équipe RÉSIF-DC et deux invité\textperiodcentered e\textperiodcentered s. Le but de cette réunion était de définir les besoins du centre de données dans le cadre du développement d'un outil de gestion de cycle de vie des données. La particularité de cette réunion était sa forme. En effet, cette réunion était découpée en plusieurs parties spécifiques pour ainsi maximiser la créativité et la productivité des intervenant\textperiodcentered e\textperiodcentered s.
|
|
|
|
|
\newpage{}
|
|
|
|
|
\section{Bilan}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
À la fin de mon stage, j'ai pu écrire en tout 172 scénarios sur six \textit{web services} différents:
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item \href{https://ws.resif.fr/fdsnws/station/1}{station}
|
|
|
|
|
\item \href{https://ws.resif.fr/fdsnws/availability/1}{availabililty} en mode \textit{query}
|
|
|
|
|
\item \href{https://ws.resif.fr/fdsnws/availability/1}{availabililty} en mode \textit{extent}
|
|
|
|
|
\item \href{https://ws.resif.fr/fdsnws/dataselect/1}{dataselect}
|
|
|
|
|
\item \href{https://ph5ws.resif.fr/fdsnws/dataselect/1}{ph5-dataelect}
|
|
|
|
|
\item \href{https://ph5ws.resif.fr/resifws/availability/1}{ph5-availability}
|
|
|
|
|
\end{itemize}
|
|
|
|
|
|
|
|
|
|
\paragraph{}
|
|
|
|
|
J'ai pu relever plusieurs bugs, par exemple, une divergence dans le comportement du \textit{web service} \textit{station} en fonction de la méthode HTTP utilisée (GET et POST) si on demande une date à la limite exterieur de ce qui est autorisé (par exemple le 21 novembre 2020 à 12h\textbf{60}). Ainsi le travail que j'ai produit a pu servir à mettre en lumière des problèmes qui n'ont pas étés repérés jusqu'à présent. Aussi, dans le cadre d'une réecriture d'un \textit{web service}, mes tests permettent de verifier qu'il n'y a pas eu de régressions par rapport à l'implémentation précédente. Ces tests peuvent aussi être lancés de manière automatique dans le cadre d'une vérification routinière du bon fonctionement des \textit{web services}. J'ai aussi documenté mon code pour une transmission du savoir plus facile.
|
|
|
|
|
\newpage{}
|
|
|
|
|
\section{Conclusion}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
J'ai pu lors de ce stage, développer des tests comportementaux pour différents \textit{web services} de RÉSIF. Ainsi, j'ai pu interagir avec les membres de mon équipe pour mieux cerner les problématiques que ce stage comprenait. J'ai donc pu travailler ma capacité d'écoute ainsi que de communication. En effet, J'ai aussi dû m'exprimer pour expliquer quels étaient les problèmes que je rencontrais, quels bugs j'avais relevé au niveau des \textit{web services} ou encore quel était l'état d'avancement de mon projet.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Hélas, j'étais la seule personne à travailler sur ce projet. En effet, travailler à plusieurs sur un même projet apporte et améliore cette capacité à travailler en équipe. Toutefois, cela reste à relativiser dans mon cas car je devais quand même faire un rapport quotidien au près de mon tuteur ainsi qu'un rapport hebdomadaire pour l'ensemble de l'équipe RÉSIF-DC.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
Cependant, j'ai quand même pu me sentir à l'aise au sein de l'équipe. En effet, l'ambiance de travail était bonne, les personnes s'entraidaient en cas de besoin, etc..
|
|
|
|
|
\newpage{}
|
|
|
|
|
\section*{Recap}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
During my internship in ISTerre, I had to realize behavior tests. Those types of tests check the behavior of a software from the outside. The pieces of software I was testing were web services. The goal of those applications is to give data depending on parameters, usualy defined and affected in a URL. There were three web services that I had to test: \textit{station}, \textit{availability} and \textit{dataselect}. Those web services give different types of data:
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item \textbf{Station} gives the context of how the data were captured
|
|
|
|
|
\item \textbf{Availability} gives time periods where there is data captured
|
|
|
|
|
\item \textbf{Dataselect} gives data depending on time period and an instrument of capture
|
|
|
|
|
\end{itemize}
|
|
|
|
|
\paragraph{}
|
|
|
|
|
A test is split in two parts: the scenario and the implementation.
|
|
|
|
|
\subparagraph{}
|
|
|
|
|
Scenario is the description of a test written in natural language (like English, French or Chinese). It is composed by three types of steps:
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item \textbf{Given}, that will initiate the context of the test
|
|
|
|
|
\item \textbf{When}, that will represent an action done by users (in my case, this is requesting a web service)
|
|
|
|
|
\item \textbf{Then}, that will test the behavior.
|
|
|
|
|
\end{itemize}
|
|
|
|
|
Of course, it is possible to have several \textit{Given}, \textit{When} and \textit{Then} but a scenario has to get at liste one of each.
|
|
|
|
|
\subparagraph{}
|
|
|
|
|
Then there is the implementation. Each step must be translated in code. To do that, I had to define function with a \textit{decorator}. The decorator must has in parameter the exact sentence written in the scenario. For exemple, the step \textit{Given the cache refreshed} will have this translation in a python file and the decorator of the function that implement the behavior of the step will looks like \textit{@given("the cache refreshed")}.
|
|
|
|
|
\paragraph{}
|
|
|
|
|
To be able to use my code several times, I had to design my code. The result of this work is that I wrote a class named \textit{Query} and a class named \textit{Response}. Thoses two classes are the most important ones of my model. With a \textit{Querry} object, you can ask a web sevice, but only if there is a subclass specilized for that (ex. \textit{StationQuery}). With a \textit{Response} object, you can access and do opperations to the response of the web service. In the same way as \textit{Query}, \textit{Response} must be specialized.
|
|
|
|
|
\newpage{}
|
|
|
|
|
\section*{Lexique}
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item \textbf{Test de comportement (behavior test)} : Test informatique permettant de vérifier le comportement du logiciel testé sur la base de différents scénarios
|
|
|
|
|
\item \textbf{Nœud A}: Équipe de sismologues chargée de placer des sondes, de récolter et traiter les données et métadonnées, et de les transmetre au nœud B
|
|
|
|
|
\item \textbf{Nœud B}: Équipe de sismologues chargée de stocker et distribuer les données et méta-données récoltées par les différents nœuds A.
|
|
|
|
|
\item \textbf{Classe}: Concept informatique permettant de regrouper des données et des fonctionnalités liés à ces données.
|
|
|
|
|
\item \textbf{Objet}: Représentation en mémoire d'une classe.
|
|
|
|
|
\item \textbf{UMR}: Une Unité Mixte de Recherche est le résultat d'une collaboration entres un ou plusieurs laboratoires de recherche d'un établissement d'enseignement supérieur\cite{umr}.
|
|
|
|
|
\item \textbf{OSU}: Un Observatoire des Sciences de l'Univers est un regroupement de laboratoires chargé de conduire des observations de longue durée dans le domaine des sciences de l’univers\cite{osu}.
|
|
|
|
|
\item \textbf{IR}: Une Infrastructure de Recherche premet au chercheur\textperiodcentered euse\textperiodcentered s de mener des recherches de grandes ampleurs dans des domaines de pointe. \cite{ir}
|
|
|
|
|
\end{itemize}
|
|
|
|
|
\newpage{}
|
|
|
|
|
\section*{Webographie}
|
|
|
|
|
\bibliographystyle{plain}
|
|
|
|
|
\bibliography{biblio}
|
|
|
|
|
\newpage{}
|
|
|
|
|
\section*{Annexes}
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Exemple requête Station en XML}
|
|
|
|
|
\href{https://ws.resif.fr/fdsnws/station/1/query?net=FR&sta=CFF&cha=HHZ&level=channel&format=xml}{\small https://ws.resif.fr/fdsnws/station/1/query?net=FR\&sta=CFF\&cha=HHZ\&level=channel\&format=xml}
|
|
|
|
|
\label{fig:URLstationXML}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Exemple reuqête Station en text}
|
|
|
|
|
\href{https://ws.resif.fr/fdsnws/station/1/query?net=FR&sta=CFF&cha=HHZ&level=channel&format=text}{\small https://ws.resif.fr/fdsnws/station/1/query?net=FR\&sta=CFF\&cha=HHZ\&level=channel\&format=text}
|
|
|
|
|
\label{fig:URLstationText}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Exemple requête Availability en text}
|
|
|
|
|
\href{https://ws.resif.fr/fdsnws/availability/1/extent?net=FR&sta=CFF&format=text}{\small https://ws.resif.fr/fdsnws/availability/1/extent?net=FR\&sta=CFF\&format=text}
|
|
|
|
|
\label{fig:URLavailabilityText}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Exemple reqête Availability en json}
|
|
|
|
|
\href{https://ws.resif.fr/fdsnws/availability/1/extent?net=FR&sta=CFF&format=json}{\small https://ws.resif.fr/fdsnws/availability/1/extent?net=FR\&sta=CFF\&format=json}
|
|
|
|
|
\label{fig:URLavailabilityJson}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\begin{figure}[H]
|
|
|
|
|
\caption{Exemple requête Availability en CSV}
|
|
|
|
|
\href{https://ws.resif.fr/fdsnws/availability/1/extent?net=FR&sta=CFF&format=geocsv}{\small https://ws.resif.fr/fdsnws/availability/1/extent?net=FR\&sta=CFF\&format=geocsv}
|
|
|
|
|
\label{fig:URLavailabilityCsv}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\begin{figure}[h]
|
|
|
|
|
\caption{Diagramme de classes pour les classes Response}
|
|
|
|
|
\includegraphics[angle=90, scale=0.5]{response}
|
|
|
|
|
\label{fig:ResponseClassDiag}
|
|
|
|
|
\end{figure}
|
|
|
|
|
\end{document}
|