29. Comment écrire un plugin pour JMeter ¶
Introduction de Peter Lin
À plus d'une occasion, les utilisateurs se sont plaints que la documentation du développeur de JMeter est obsolète et pas très utile. Afin de faciliter la tâche des développeurs, j'ai décidé d'écrire un didacticiel simple, étape par étape. Lorsque j'en ai parlé à Mike, il avait quelques idées sur ce que le tutoriel devrait couvrir.
Avant de plonger dans le tutoriel, j'aimerais dire que l'écriture d'un plugin n'est pas nécessairement facile, même pour quelqu'un qui a plusieurs années d'expérience en Java. La première extension que j'ai écrite pour JMeter était un utilitaire simple pour analyser les journaux d'accès HTTP et produire des requêtes au format XML. Ce n'était pas vraiment un plugin, car c'était un utilitaire de ligne de commande autonome. Mon premier vrai plugin pour JMeter était l'échantillonneur de service Web. Je travaillais sur un projet .NET et j'avais besoin de tester un service Web. La plupart des outils commerciaux disponibles pour tester les services Web .NET sont nuls et coûtent trop cher. Plutôt que de débourser plusieurs centaines de dollars pour un outil de test boiteux, ou quelques milliers de dollars pour un bon, j'ai décidé qu'il était plus facile et moins cher d'écrire un plugin pour JMeter.
Après deux semaines de codage sur mon temps libre, j'avais un prototype fonctionnel utilisant le pilote Apache Soap. Je l'ai renvoyé à JMeter et Mike m'a demandé si je voulais être un committer. J'avais contribué des correctifs à Jakarta JSTL et tomcat dans le passé, donc je considérais cela comme un honneur. Depuis lors, j'ai écrit l'échantillonneur de journal d'accès, le moniteur Tomcat 5 et le graphique de distribution. Depuis lors, Mike a considérablement amélioré l'échantillonneur de journal d'accès et l'a rendu beaucoup plus utile.
Présentation de Mike Stover
L'un de mes principaux objectifs lors de la conception de JMeter était de faciliter l'écriture de plugins pour améliorer autant de fonctionnalités de JMeter que possible. Une partie de l'avantage d'être open-source est que beaucoup de gens pourraient potentiellement prêter leurs efforts pour améliorer l'application. J'ai pris la décision consciente de sacrifier une certaine simplicité dans le code pour faire de l'écriture de plugins un mode de vie pour un développeur JMeter.
Alors que certaines personnes ont réussi à creuser directement dans le code et à apporter des améliorations à JMeter, un véritable tutoriel sur la façon de procéder fait défaut. J'ai essayé il y a longtemps d'écrire de la documentation à ce sujet, mais la plupart des gens ne l'ont pas trouvé utile. Espérons qu'avec l'aide de Peter, cette tentative sera plus fructueuse.
29.1 Structure de base de JMeter ¶
JMeter est organisé par protocoles et fonctionnalités. Ceci est fait pour que les développeurs puissent créer de nouveaux jars pour un seul protocole sans avoir à créer l'intégralité de l'application. Nous entrerons dans les détails de la construction de JMeter plus tard dans le didacticiel. Étant donné que la plupart des développeurs JMeter utilisent eclipse, l'article utilisera le répertoire eclipse comme point de référence.
Répertoire racine - /eclipse/workspace/apache-jmeter/
Les dossiers à l'intérieur d' apache-jmeter
- poubelle
- contient les fichiers .bat et .sh pour démarrer JMeter. Il contient également ApacheJMeter.jar et le fichier de propriétés
- build/docs
- répertoire contient les fichiers de documentation JMeter
- Suppléments
- fichiers supplémentaires liés aux fourmis
- bibliothèque
- contient les fichiers jar requis pour JMeter
- lib/ext
- contient les fichiers jar de base pour JMeter et les protocoles
- src
- contient un sous-répertoire pour chaque protocole et composant
- src/*/test
- répertoire lié aux tests unitaires
- xdocs
- Fichiers XML pour la documentation. JMeter génère sa documentation à partir de XML.
Au fur et à mesure que le didacticiel progresse, une explication des sous-répertoires sera fournie. Pour l'instant, concentrons-nous sur le répertoire src .
Les dossiers à l'intérieur de src
- bshclient
- code pour le client basé sur BeanShell
- verrouiller
- code pour le protocole Bolt
- Composants
- contient des composants non spécifiques au protocole tels que des visualiseurs, des assertions, etc.
- cœur
- le code de base de JMeter, y compris toutes les interfaces de base et les classes abstraites.
- distance
- construit un script qui crée une distribution
- dist-check
- code lié au test de la distribution. C'est l'endroit à rechercher lorsque vous souhaitez mettre à jour le contenu de l'archive source/binaire résultante
- exemples
- exemple d'échantillonneur montrant comment utiliser le nouveau cadre de bean
- les fonctions
- fonctions standard utilisées par tous les composants
- Générateur
- code pour générer un plan de test avec tous les éléments. Utilisé pour tester la distribution
- jorphan
- classes utilitaires fournissant des fonctions utilitaires communes
- lanceur
- code pour aider à démarrer et arrêter JMeter via l'API
- licences
- contient des informations sur les licences utilisées dans les dépendances JMeters
- protocole
- contient les différents protocoles supportés par JMeter
- Libération
- code lié à la publication de la distribution JMeter
- kit de test
- code utilitaire pour les tests
- testkit-wiremock
- code utilitaire pour tester avec WireMock
Dans le répertoire de protocole , se trouvent les composants spécifiques au protocole.
Les dossiers à l'intérieur du protocole
- ftp
- composants pour tester la charge des serveurs ftp
- http
- composants pour les tests de charge des serveurs Web
- Java
- composants pour les tests de charge des composants java
- jdbc
- composants pour tester la charge des serveurs de base de données à l'aide de JDBC
- jm
- composants pour tester la charge des serveurs JMS
- Junit
- composants pour test de charge à l'aide de tests JUnit
- junit-échantillon
- exemples d'implémentations de test basées sur JUnit
- LDAP
- composants pour tester la charge des serveurs LDAP
- courrier
- composants pour tester la charge des serveurs de messagerie
- originaire de
- composants pour les tests de charge commandes natives du système d'exploitation
- TCP
- composants pour tester la charge des services TCP
En règle générale, tous les échantillonneurs liés à HTTP résideront dans le répertoire http . L'exception à la règle est le moniteur Tomcat5. Il est distinct, car la fonctionnalité du moniteur est légèrement différente de celle des tests d'effort ou fonctionnels. Il pourra éventuellement être réorganisé, mais pour l'instant il se trouve dans son propre répertoire. En termes de difficulté, écrire des visualiseurs est probablement l'un des plugins les plus difficiles à écrire.
29.2 JMeter Gui – Contrat TestElement ¶
Lors de l'écriture d'un composant JMeter, vous devez connaître certains contrats - la manière dont un composant JMeter est censé se comporter s'il s'exécute correctement dans l'environnement JMeter. Cette section décrit le contrat que la partie GUI de votre composant doit respecter.
Le code GUI dans JMeter est strictement séparé du code Test Element. Par conséquent, lorsque vous écrivez un composant, il y aura une classe pour l'élément de test et une autre pour la présentation de l'interface graphique. La classe de présentation de l'interface graphique est sans état dans le sens où elle ne doit jamais s'accrocher à une référence à l'élément de test (il existe cependant des exceptions à cela).
Un élément GUI doit étendre la classe abstraite appropriée fournie :
- RésuméSamplerGui
- AbstraitAssertionGui
- AbstractConfigGui
- RésuméControllerGui
- AbstractPostProcessorGui
- AbstractPreProcessorGui
- Visualiseur abstrait
- AbstractTimerGui
Ces classes abstraites vous fournissent tellement de travail de plomberie que ne pas les étendre, et plutôt implémenter directement les interfaces n'est guère une option. Si vous avez un besoin impérieux de ne pas prolonger ces cours, alors vous pouvez me rejoindre sur IRC où je peux vous convaincre du contraire :-).
Donc, vous avez étendu la classe GUI appropriée, que reste-t-il à faire ? Suivez ces étapes:
- Implémenter getLabelResource()
- Cette méthode doit renvoyer le nom de la ressource qui représente le titre/nom du composant. La ressource devra être entrée dans le fichier messages.properties de JMeters (et éventuellement les traductions également).
- Créez votre interface graphique. Quel que soit le style que vous aimez, agencez votre interface graphique. Votre classe étend finalement
JPanel , donc votre mise en page doit être dans le ContentPane de votre classe . N'associez pas d'éléments d'interface graphique à votre classe TestElement via des actions et des événements. Laissez le modèle interne de swing s'accrocher à toutes les données autant que possible.
- Certains éléments d'interface graphique standard doivent être ajoutés à tous les composants d'interface graphique JMeter :
- Appelez setBorder(makeBorder()) pour votre classe. Cela lui donnera la bordure JMeter standard
- Ajoutez le volet de titre via makeTitlePanel() . Il s'agit généralement de la première chose ajoutée à votre interface graphique et doit être effectuée dans un schéma de disposition verticale Box ou avec la classe VerticalLayout de JMeter
. Voici un exemple de méthode init() :
vide privé init() { setLayout(nouveau BorderLayout()); setBorder(makeBorder()); Boîte boîte = Boîte.createVerticalBox(); box.add(makeTitlePanel()); box.add(makeSourcePanel()); add(box,BorderLayout.NORTH); add(makeParameterPanel(),BorderLayout.CENTER); }
- Certains éléments d'interface graphique standard doivent être ajoutés à tous les composants d'interface graphique JMeter :
- Implémenter public void configure(TestElement el)
- Assurez-vous d'appeler super.configure(e) . Cela remplira certaines des données pour vous, comme le nom de l'élément.
- Utilisez cette méthode pour définir des données dans vos éléments d'interface graphique. Exemple:
public void configure(TestElement el) { super.configure(el); useHeaders.setSelected( el.getPropertyAsBoolean(RegexExtractor.USEHEADERS)); useBody.setSelected( !el.getPropertyAsBoolean(RegexExtractor.USEHEADERS)); regexField.setText( el.getPropertyAsString(RegexExtractor.REGEX)); templateField.setText( el.getPropertyAsString(RegexExtractor.TEMPLATE)); defaultField.setText( el.getPropertyAsString(RegexExtractor.DEFAULT)); matchNumberField.setText( el.getPropertyAsString(RegexExtractor.MATCH_NUM)); refNameField.setText( el.getPropertyAsString(RegexExtractor.REFNAME)); }
- Implémentez public void modifyTestElement(TestElement e) . C'est là que vous déplacez les données de vos éléments GUI vers le TestElement . C'est l'inverse logique de la méthode précédente.
- Appelez super.configureTestElement(e) . Cela prendra soin de certaines données par défaut pour vous.
- Exemple:
public void modifyTestElement(TestElement e) { super.configureTestElement(e); e.setProperty(new BooleanProperty( RegexExtractor.USEHEADERS, useHeaders.isSelected())); e.setProperty(RegexExtractor.MATCH_NUMBER, matchNumberField.getText()); if (e instanceof RegexExtractor) { RegexExtractor regex = (RegexExtractor)e ; regex.setRefName(refNameField.getText()); regex.setRegex(regexField.getText()); regex.setTemplate(templateField.getText()); regex.setDefaultValue(defaultField.getText()); } }
- Implémentez public TestElement createTestElement() . Cette méthode doit créer une nouvelle instance de votre classe TestElement , puis la transmettre à la méthode modifyTestElement(TestElement)
que vous avez créée ci-dessus
public TestElement createTestElement() { Extracteur RegexExtractor = new RegexExtractor(); modifyTestElement(extracteur); extracteur de retour; }
La raison pour laquelle vous ne pouvez pas conserver une référence pour votre élément de test est que JMeter réutilise une instance d'objets de classe GUI pour plusieurs éléments de test. Cela économise beaucoup de mémoire. Cela rend également incroyablement facile l'écriture de la partie graphique de votre nouveau composant. Vous devez toujours lutter avec la mise en page dans Swing, mais vous n'avez pas à vous soucier de créer les bons événements et actions pour obtenir les données des éléments de l'interface graphique dans le TestElement où cela peut faire du bien. JMeter sait quand appeler vos méthodes configure et modifyTestElement où vous pouvez le faire de manière très simple.
Cependant, l'écriture de visualiseurs est un cas particulier.
29.3 Écrire un visualiseur ¶
Parmi les types de composants, les visualiseurs nécessitent une plus grande profondeur dans Swing que quelque chose comme les contrôleurs, les fonctions ou les échantillonneurs. Vous pouvez trouver la source complète du graphique de distribution dans components/org/apache/jmeter/visualizers/ . Le visualiseur de graphique de distribution est divisé en deux classes.
- DistributionGraphVisualizerDistributionGraphVisualizer
- visualiseur que JMeter instancie
- DistributionGraph
- JComponent qui dessine le graphe réel
La manière la plus simple d'écrire un visualiseur est de procéder comme suit :
- Étendre org.apache.jmeter.visualizers.gui.AbstractVisualizer
- Implémentez toutes les interfaces supplémentaires nécessaires pour le rappel et la notification d'événements. Par exemple, DistributionGraphVisualizer implémente les interfaces suivantes :
- ImageVisualizer
- ItemListener - selon les commentaires de la classe, ItemListener est obsolète et n'est plus utilisé.
- GraphListener
- Effacable
AbstractVisualizer fournit certaines fonctionnalités communes, que la plupart des visualiseurs comme Graph Results utilisent. La fonctionnalité commune fournie par la classe abstraite comprend :
- Configurer les éléments de test - Cela signifie qu'il crée un nouveau ResultCollector , définit le fichier et définit le journal des erreurs
- Créer le menu des stocks
- Mettre à jour l'élément de test lorsque des modifications sont apportées
- Créer un panneau de fichiers pour le fichier journal
- Créer le panneau de titre
Dans certains cas, vous ne souhaiterez peut-être pas afficher le menu de la zone de texte du fichier. Dans ce cas, vous pouvez remplacer la méthode init() . Voici l'implémentation de DistributionGraphVisualizer .
/** * Initialiser l'interface graphique. */ vide privé init() { this.setLayout(new BorderLayout()); // PANNEAU PRINCIPAL Marge de bordure = new EmptyBorder(10, 10, 5, 10); this.setBorder(marge); // Configurez le graphique avec l'en-tête, le pied de page, l'axe Y et l'affichage du graphique JPanel graphPanel = new JPanel(new BorderLayout()); graphPanel.add(createGraphPanel(), BorderLayout.CENTER); graphPanel.add(createGraphInfoPanel(), BorderLayout.SOUTH); // Ajout du panneau principal et du graphique this.add(makeTitlePanel(), BorderLayout.NORTH); this.add(graphPanel, BorderLayout.CENTER); }
La première chose que fait la méthode init est de créer un nouveau BorderLayout . Selon la façon dont vous souhaitez disposer les widgets, vous pouvez utiliser un gestionnaire de disposition différent. Gardez à l'esprit que l'utilisation de différents gestionnaires de mise en page est réservée aux experts.
La deuxième chose que fait la méthode init est de créer une bordure. Si vous souhaitez augmenter ou diminuer la bordure, modifiez les quatre valeurs entières. Chaque valeur entière représente des pixels. Si vous souhaitez que votre visualiseur n'ait pas de bordure, ignorez les lignes 8 et 9. La ligne 13 appelle createGraphPanel , qui est responsable de la configuration et de l'ajout du DistributionGraph au visualiseur.
Composant privé createGraphPanel() { graphPanel = new JPanel(); graphPanel.setBorder(BorderFactory.createBevelBorder( BevelBorder.LOWERED, Color.lightGray, Color.darkGray)); graphPanel.add(graphe); graphPanel.setBackground(Color.white); retourne graphPanel ; }
À la ligne 5, le composant graphique est ajouté au panneau graphique. Le constructeur est l'endroit où une nouvelle instance de DistributionGraph est créée.
public DistributionGraphVisualizer() { model = new SamplingStatCalculator("Distribution"); graph = new DistributionGraph(modèle); graph.setBackground(Color.white); init(); }
Le constructeur de DistributionGraphVisualizer est responsable de la création du modèle et du graphe. Chaque fois qu'un nouveau résultat est terminé, le moteur transmet le résultat à tous les écouteurs en appelant add(SampleResult res) . Le visualiseur transmet le nouveau SampleResult au modèle.
void synchronisé public add(SampleResult res) { model.addSample(res); updateGui(model.getCurrentSample()); }
Dans le cas de DistributionGraphVisualizer , la méthode add ne met pas réellement à jour le graphique. Au lieu de cela, il appelle updateGui à la ligne trois.
public synchronized void updateGui(Sample s) { // Nous avons reçu un autre échantillon si (délai == compteur) { updateGui(); compteur = 0 ; } autre { compteur++ ; } }
Contrairement à GraphVisualizer , le graphique de distribution tente de montrer comment les résultats s'agglutinent ; par conséquent, le DistributionGraphVisualizer retarde la mise à jour. Le délai par défaut est de 10 échantillons de résultats.
public synchronisé void updateGui() { si (graph.getWidth() < 10) { graph.setPreferredSize( nouvelle dimension(getWidth() - 40, getHeight() - 160)); } graphPanel.updateUI(); graph.repaint(); }
Les lignes 2 à 3 sont supposées redimensionner le graphique, si l'utilisateur redimensionne la fenêtre ou fait glisser le séparateur. La ligne 7 met à jour le panneau contenant le graphique. La ligne 8 déclenche la mise à jour du DistributionGraph . Avant de couvrir l'écriture de graphiques, il y a quelques méthodes importantes que le visualiseur doit implémenter.
chaîne publique getLabelResource() { renvoie "distribution_graph_title" ; }
La ressource label récupère le nom du visualiseur à partir du fichier de propriétés. Le fichier se trouve dans core/org/apache/jmeter/resources . Il est préférable de ne pas coder en dur le nom du visualiseur. Le fichier Message.properties est organisé par ordre alphabétique, ce qui facilite l'ajout d'une nouvelle entrée.
public synchronisé void clear() { this.graph.clear(); model.clear(); repeindre(); }
Chaque composant de JMeter doit implémenter la logique de la méthode clear() . Si cela n'est pas fait, le composant n'effacera pas l'interface utilisateur ou le modèle lorsque l'utilisateur essaiera d'effacer les derniers résultats et d'exécuter un nouveau test. Si clear n'est pas implémenté, cela peut entraîner une fuite de mémoire.
public JComponent getPrintableComponent() { retourne this.graphPanel ; }
La dernière méthode que les visualiseurs doivent implémenter est getPrintableComponent() . La méthode est chargée de renvoyer le JComponent qui peut être enregistré ou imprimé. Cette fonctionnalité a été récemment ajoutée afin que les utilisateurs puissent enregistrer une capture d'écran de n'importe quel visualiseur donné.
29.4 GraphListener ¶
Les visualiseurs doivent implémenter GraphListener . Ceci est fait pour simplifier l'ajout de nouvelles instances d'échantillons aux écouteurs. En règle générale, si le graphique personnalisé ne trace pas chaque échantillon, il n'a pas besoin d'implémenter l'interface.
interface publique GraphListener { public void updateGui(Sample s); public void updateGui(); }
La méthode importante dans l'interface est updateGui(Sample s) . De DistributionGraphVisualizer , nous voyons qu'il appelle graph.repaint() pour actualiser le graphique. Dans la plupart des cas, l'implémentation de updateGui(Sample s) devrait faire exactement cela. Les ItemListenerVisualizers n'ont généralement pas besoin d'implémenter cette interface. L'interface est utilisée avec des listes déroulantes, des cases à cocher et des listes. Si votre visualiseur utilise l'un de ces éléments et a besoin de savoir quand il a été mis à jour, le visualiseur devra implémenter l'interface. Pour un exemple d'implémentation de l'interface, veuillez consulter GraphVisualizer .
29.5 Écrire des graphiques personnalisés ¶
Pour ceux qui découvrent Swing et qui n'ont pas encore écrit de JComponents personnalisés, je suggérerais de lire un livre sur Swing et d'avoir une bonne idée du fonctionnement des widgets Swing. Ce didacticiel ne tentera pas d'expliquer les concepts de base de Swing et suppose que le lecteur est déjà familiarisé avec l'API Swing et le modèle de conception MVC (Model View Controller). À partir du constructeur de DistributionGraphVisualizer , nous voyons qu'une nouvelle instance de DistributionGraph est créée avec une instance du modèle.
public DistributionGraph (modèle SamplingStatCalculator) { cette(); setModel(modèle); }
L'implémentation de la méthode setModel est simple.
setModel vide privé (modèle objet) { this.model = (SamplingStatCalculator) modèle ; repeindre(); }
Notez que la méthode appelle repaint après avoir défini le modèle. Si repaint n'est pas appelé, cela peut empêcher l'interface graphique de dessiner le graphique. Une fois le test démarré, le graphique se redessine, donc appeler repeindre n'est pas critique.
public void paintComponent(Graphics g) { super.paintComponent(g); SamplingStatCalculator final m = this.model ; synchronisé (m) { drawSample(m, g); } }
L'autre aspect important de la mise à jour du widget consiste à placer l'appel à drawSample dans un bloc synchronisé. Si drawSample n'était pas synchronisé, JMeter lèverait une ConcurrentModificationException au moment de l'exécution. Selon le plan de test, il peut y avoir une douzaine de threads ou plus ajoutant des résultats au modèle. Le bloc synchronisé n'affecte pas la précision de chaque demande individuelle et la mesure du temps, mais il affecte la capacité de JMeter à générer des charges importantes. À mesure que le nombre de threads dans un plan de test augmente, la probabilité qu'un thread doive attendre que le graphique ait fini de se redessiner avant de démarrer une nouvelle requête augmente. Voici l'implémentation de drawSample .
private void drawSample (modèle SamplingStatCalculator, Graphics g) { largeur = getWidth(); double hauteur = (double)getHeight() - 1.0 ; // dessinons d'abord la grille pour (int y=0; y < 4; y++){ int q1 = (int)(hauteur - (hauteur * 0,25 * y)); g.setColor(Color.lightGray); g.drawLine(xborder,q1,width,q1); g.setColor(Color.black); g.drawString(String.valueOf((25 * y) + "%"),0,q1); } g.setColor(Color.black); // dessine l'axe X g.drawLine(xborder,(int)height,width,(int)height); // dessine l'axe Y g.drawLine(xborder,0,xborder,(int)height); // le plan de test doit avoir plus de 200 échantillons // pour qu'il génère une distribution décente à mi-chemin // graphique. Plus l'échantillon est grand, meilleure est la // résultats. si (modèle != null && modèle.getCount() > 50) { // dessine maintenant le graphique à barres Nombre quatre-vingt-dix = model.getPercentPoint(0.90); Numéro cinquante = model.getPercentPoint(0.50); total = modèle.getCount(); Valeurs de collection = model.getDistribution().values(); Object[] objval = new Object[values.size()] ; objval = values.toArray(objval); // on trie les objets Arrays.sort(objval,new NumberComparator()); int len = objval.longueur ; for (int count=0; count < len; count++) { // calcule la hauteur Nombre[] num = (Nombre[])objval[nombre] ; double iper = (double)num[1].intValue() / (double)total ; double iheight = hauteur * iper ; // si la hauteur est inférieure à un, nous la définissons // à un pixel si (ihauteur < 1) { ihauteur = 1.0 ; } int ix = (count * 4) + xborder + 5 ; int dheight = (int)(hauteur - iheight); g.setColor(Color.blue); g.drawLine(ix -1,(int)height,ix -1,height); g.drawLine(ix,(int)height,ix,height); g.setColor(Color.black); // dessine une ligne rouge pour 90% point if (num[0].longValue() == quatre-vingt-dix.longValue()) { g.setColor(Color.red); g.drawLine(ix,(int)height,ix,55); g. drawLine(ix,(int)35,ix,0); g.drawString("90%",ix - 30,20); g. drawString( String.valueOf(num[0].longValue()), ix + 8, 20); } // dessine une ligne orange pour 50% point si (num[0].longValue() == cinquante.longValue()) { g.setColor(Color.orange); g.drawLine(ix,(int)height,ix,30); g.drawString("50%",ix - 30,50); g. drawString( String.valueOf(num[0].longValue()), ix + 8, 50); } } } }
En général, le rendu du graphique devrait être assez rapide et ne devrait pas être un goulot d'étranglement. En règle générale, c'est une bonne idée de profiler les plugins personnalisés. La seule façon de s'assurer qu'un visualiseur n'est pas un goulot d'étranglement est de l'exécuter avec un outil comme Borland OptimizeIt. Un bon moyen de tester un plugin est de créer un plan de test simple et de l'exécuter. Le comportement du tas et de la récupération de place doit être régulier et prévisible.
29.6 Création d'un plugin TestBean pour JMeter ¶
Dans cette partie, nous allons passer par le processus de création d'un composant simple pour JMeter qui utilise le nouveau framework TestBean .
Ce composant sera un élément de lecture de fichier CSV qui permettra aux utilisateurs de varier facilement leurs données d'entrée à l'aide de fichiers CSV. Pour utiliser plus efficacement ce didacticiel, ouvrez les trois fichiers spécifiés ci-dessous (qui se trouvent dans le répertoire src/components de JMeter ).
- Choisissez un package et créez trois fichiers :
- [ComponentName].java (org.apache.jmeter.config.CSVDataSet.java)
- [ComponentName]BeanInfo.java (org.apache.jmeter.config.CSVDataSetBeanInfo.java)
- [ComponentName]Resources.properties (org.apache.jmeter.config.CSVDataSetResources.properties)
-
CSVDataSet.java doit implémenter l' interface TestBean . De plus, il étendra
ConfigTestElement et implémentera LoopIterationListener .
- TestBean est une interface de marqueur, il n'y a donc aucune méthode à implémenter.
- L'extension de ConfigTestElement fera de notre composant un élément Config dans un plan de test. En étendant différentes classes abstraites, vous pouvez contrôler le type d'élément de votre composant (c'est-à-dire AbstractSampler , AbstractVisualizer , GenericController , etc. - bien que vous puissiez également créer différents types d'éléments simplement en instanciant les bonnes interfaces, les classes abstraites peuvent rendre votre vie Plus facile).
-
CSVDataSetBeanInfo.java doit étendre org.apache.jmeter.testbeans.BeanInfoSupport
- créer un constructeur à paramètre zéro dans lequel nous appelons super(CSVDataSet.class);
- nous y reviendrons.
- CSVDataSetResources.properties - vide pour l'instant
- Implémentez votre logique spéciale pour votre classe de plugin.
- Le CSVDataSet lira un seul fichier CSV et stockera les valeurs qu'il trouve dans le contexte d'exécution de JMeter. L'utilisateur définira le fichier, définira les noms des variables pour chaque " colonne ". Le CSVDataSet ouvrira le fichier au démarrage du test et le fermera à la fin du test (ainsi, nous implémentons TestListener ). Le CSVDataSet mettra à jour le contenu des variables pour chaque thread de test et pour chaque itération via son contrôleur parent, en lisant de nouvelles lignes dans le fichier. Lorsque nous arrivons à la fin du fichier, nous recommencerons au début. Lors de l'implémentation d'un TestBean, portez une attention particulière à vos propriétés. Ces propriétés deviendront la base d'un formulaire GUI par lequel les utilisateurs configureront l' élément CSVDataSet .
- Votre élément sera cloné par JMeter au démarrage du test. Chaque thread aura sa propre instance. Cependant, vous aurez la possibilité de contrôler la façon dont le clonage est effectué, si vous en avez besoin.
- Propriétés : filename , variableNames . Avec des getters et des setters publics.
- filename est explicite, il contiendra le nom du fichier CSV que nous lirons
- variableNames est une chaîne qui permettra à un utilisateur d'entrer les noms des variables auxquelles nous attribuerons des valeurs. Pourquoi une chaîne ? Pourquoi pas une Collection ? Les utilisateurs devront sûrement saisir plusieurs noms de variables (et un nombre inconnu de) ? C'est vrai, mais si nous utilisions une liste ou une collection, nous aurions à écrire un composant graphique pour gérer les collections, et je veux juste le faire rapidement. Au lieu de cela, nous laisserons les utilisateurs saisir une liste de noms de variables délimitée par des virgules.
- J'ai ensuite implémenté la méthode IterationStart de l' interface LoopIterationListener . Le but de cet "événement" est que votre composant est averti lorsque le test est entré dans son contrôleur parent. Pour nos besoins, chaque fois que le contrôleur parent du CSVDataSet est entré, nous allons lire une nouvelle ligne du fichier de données et définir les variables. Ainsi, pour un contrôleur standard, chaque boucle du test entraînera la lecture d'un nouvel ensemble de valeurs. Pour un contrôleur de boucle, chaque itération fera de même. Chaque thread de test obtiendra également des valeurs différentes.
- Configuration de vos éléments d'interface graphique dans CSVDataSetBeanInfo :
- Vous pouvez créer des regroupements pour les propriétés de votre composant. Chaque groupement que vous créez nécessite une étiquette et une liste de noms de propriétés à inclure dans ce groupement. C'est à dire:
createPropertyGroup("csv_data", new String[] { "filename", "variableNames" });
- Crée un regroupement appelé csv_data qui inclura des éléments d'entrée GUI pour les
propriétés filename et variableNames de CSVDataSet . Ensuite, nous devons définir le type de propriétés que nous voulons :
p = propriété("nom de fichier"); p.setValue(NOT_UNDEFINED, Boolean.TRUE); p.setValue(DEFAULT, ""); p.setValue(NOT_EXPRESSION, Boolean.TRUE); p = propriété("variableNames"); p.setValue(NOT_UNDEFINED, Boolean.TRUE); p.setValue(DEFAULT, ""); p.setValue(NOT_EXPRESSION, Boolean.TRUE);
Cela crée essentiellement deux propriétés dont la valeur n'est pas autorisée à être null et dont les valeurs par défaut sont "" . Plusieurs attributs de ce type peuvent être définis pour chaque propriété. Voici un aperçu :- NOT_UNDEFINED
- La propriété ne sera pas laissée null .
- DÉFAUT
- Une valeur par défaut doit être donnée si NOT_UNDEFINED est true .
- NOT_EXPRESSION
- La valeur ne sera pas analysée pour les fonctions si cela est vrai .
- NOT_OTHER
- Il ne s'agit pas d'un champ de saisie libre - une liste de valeurs doit être fournie.
- MOTS CLÉS
- Avec un String [] comme valeur, cela établit une liste prédéfinie de valeurs acceptables, et JMeter créera une sélection déroulante.
p.setPropertyEditorClass(FileEditor.class);
Cela créera une entrée de texte plus un bouton de navigation qui ouvre une boîte de dialogue pour rechercher un fichier. Habituellement, les paramètres de propriété complexes ne sont pas nécessaires, comme maintenant. Pour un exemple plus complexe, regardez org.apache.jmeter.protocol.http.sampler.AccessLogSamplerBeanInfo
- Vous pouvez créer des regroupements pour les propriétés de votre composant. Chaque groupement que vous créez nécessite une étiquette et une liste de noms de propriétés à inclure dans ce groupement. C'est à dire:
- Définition de vos chaînes de ressources. Dans CSVDataSetResources.properties, nous devons définir toutes nos ressources de chaîne. Pour fournir des traductions, il faudrait créer des fichiers supplémentaires tels que
CSVDataSetResources_ja.properties et CSVDataSetResources_de.properties . Pour notre composant, nous devons définir les ressources suivantes :
- Afficher un nom
- Cela fournira un nom à l'élément qui apparaîtra dans les menus.
- csv_data.displayName
- nous créons un groupe de propriétés appelé csv_data , nous devons donc fournir une étiquette pour le groupe
- filename.displayName
- une étiquette pour l'élément d'entrée du nom de fichier.
- filename.shortDescription
- un texte d'aide en forme d'info-bulle.
- variableNames.displayName
- une étiquette pour l'élément d'entrée de nom de variable.
- variableNames.shortDescription
- info-bulle pour l' élément d'entrée variableNames .
- Déboguez votre composant.
29.6 Construire JMeter ¶
JMeter utilise Gradle pour compiler et construire la distribution. JMeter a plusieurs tâches définies, ce qui permet aux développeurs de créer plus facilement le projet complet. Pour ceux qui ne sont pas familiers avec Gradle, c'est un outil de build similaire à make sur Unix. Une liste des tâches Gradle avec une courte description est fournie dans gradle.md , qui se trouve dans le répertoire source racine.
Voici quelques exemples de commandes.
- ./gradlew runGui
- Construire et démarrer l'interface graphique JMeter
- ./gradlew createDist
- Générez le projet et copiez les fichiers jar pertinents dans le dossier ./lib
- ./gradlew :src:dist:previewSite
- Crée un aperçu d'un site dans ./build/docs/site