Webdriverio: Possibilité de configurer le frai du processus de spécification de test ?

Créé le 14 avr. 2016  ·  41Commentaires  ·  Source: webdriverio/webdriverio

Le problème

Selon https://github.com/webdriverio/webdriverio/issues/1106#issuecomment -184728530 each test spec gets executed in a single child process .
Nous avons actuellement 101 .feature files individuels (nous utilisons du concombre) et ne pouvons pas les mettre dans un seul gros fichier.
Lorsque nous lançons notre script de test, mon serveur Selenium essaie de générer le processus 101, cela entraîne un décalage très important et je dois tuer les processus.

Existe-t-il un moyen de configurer ce comportement ? Avons-nous besoin d'ajuster notre wdio.conf ?

Environnement

mis à jour le 05/07/16

  • Version WebdriverIO : 4.1.1
  • Version de Node.js : 4.4.6
  • Serveur Sélénium 2.53.0
  • en utilisant wdio testrunner
  • exécuter des tests synchrones ou asnychrones : peu importe
  • Packages wdio supplémentaires utilisés (le cas échéant) :
    wdio-concombre-framework : 0.2.0

Des détails

Même avec les balises d'option de concombre comme -cucumberOpts.tags=@foo , cela générera 101 processus, même si une seule fonctionnalité a été étiquetée avec @foo
(Remarque : la configuration fonctionne correctement avec wdio 3.4.0)

Enhancement

Commentaire le plus utile

Nous essaierons de trouver un moyen de contourner cela dans la v5

Tous les 41 commentaires

J'ai le même problème +1 pour résoudre ce problème.

@timbru31 @AndrewKeig, veuillez vérifier la propriété maxInstance . Vous pouvez les appliquer globalement pour toutes les capacités ou une spécifique par capacité :

https://github.com/webdriverio/webdriverio/blob/master/examples/wdio.conf.js#L52 -L60
https://github.com/webdriverio/webdriverio/blob/master/examples/wdio.conf.js#L69 -L72

salut @christian-bromann, nous avons défini ce paramètre sur maxInstance:1 , mais quelles que soient les balises définies, il générera toujours un processus et ouvrira une fenêtre de navigateur vide, pour chaque fichier de fonctionnalité, exécutera 0 test et fermera. Il exécute les tests balisés une fois qu'il atteint le fichier de fonctionnalités balisé.

Même si un fichier de fonctionnalités est vide, il ouvre une fenêtre de navigateur vide et ne fait rien, puis le ferme, il semble donc qu'il ouvre une nouvelle fenêtre de navigateur quels que soient les tests activés dans un fichier de fonctionnalités.

J'espère que cela a du sens..

@AndrewKeig semble que nous pouvons améliorer l'intégration du concombre ici. Pouvez-vous déposer un problème dans le projet wdio-concombre avec une description détaillée afin que je puisse le reproduire et le comprendre ? Merci!

@AndrewKeig @christian-bromann rencontre le même problème. Pouvez-vous me taguer si vous créez un problème ? (réf https://github.com/webdriverio/wdio-cucumber-framework/issues/8)

@christian-bromann Je viens de tester cela avec du moka et j'obtiens le même bug. J'ai utilisé fgrep dans mochaOpts pour exécuter uniquement des tests spécifiques et j'ai constaté qu'une nouvelle session est initialisée dans Selenium, qu'il y ait des tests à exécuter ou non.

Après tout, cela ne semble pas être un problème spécifique au framework de test. Est-il possible dans l'API de l'adaptateur de framework d'assembler/compiler des fichiers de test avant qu'une session sélénium ne soit lancée, en fonction de critères spécifiques au framework dans l'adaptateur, par exemple des balises de fonctionnalité de concombre ou des valeurs de configuration moka grep/fgrep ?

Je pense que cette question pourrait être rouverte ici aussi pour élaborer davantage?

Je pense que cette question pourrait être rouverte ici aussi pour élaborer davantage?

D'accord, je pense que cela ne peut pas être résolu au niveau du framework car la session Selenium a déjà commencé si l'adaptateur de framework commence à fonctionner. Toutes les suggestions sont les bienvenues. Je pensais qu'il serait peut-être préférable d'avoir une fonctionnalité spécifique à wdio grep / fgrep et d'ignorer celles du framework. La question est de savoir comment vérifier efficacement les fichiers de test pour ceux-ci.

Je pense qu'il vaudrait la peine de penser à ajouter une autre étape à l'API de l'adaptateur de framework dans laquelle les adaptateurs doivent analyser et renvoyer les fichiers de fonctionnalités/spécifications requis en utilisant leur propre logique spécifique au framework. Sur cette base (et maxInstances , etc.) webdriverio pourrait déterminer combien de processus il doit générer ?

Lorsqu'un adaptateur de framework n'implémente pas cette méthode, il peut revenir au comportement par défaut (actuel).

@attila bonne idée, j'espère que les méthodes qui déterminent les fichiers à exécuter sont en quelque sorte accessibles au public.

J'ai le même problème et je sais comment le résoudre localement.

Ma solution de contournement

npm test --suite="login" --grep="oauth"
  1. Analyser les arguments de ligne de commande (valeur --grep)
  2. Obtenez tous les fichiers de notre suite
  3. Analysez nos cas de test comme new RegExp( describe\s_(\s_${name}\s*) ) ;
  4. Passer toutes les spécifications filtrées au lanceur
new WebDriverIO.Launcher('conf.js', {
    spec: [FILTERED_FILES] 
});

@christian-bromann, pourrions-nous transmettre nos spécifications au lanceur ?

C'est vraiment pénible pour mes développeurs.

@christian-bromann J'ai trouvé le coupable.
C'est dans la boucle while https://github.com/webdriverio/webdriverio/blob/master/lib/launcher.js#L194 . Étant donné que la spécification est un gros globe, elle est bouclée et à chaque fois (avec la première spécification supprimée) appelée à nouveau pour s'exécuter.

Au lieu de cela, il devrait être appelé une fois avec toutes les spécifications, car le concombre gère lui-même l'exécution avec des balises et non des balises (~ balises @foo ), n'est-ce pas ?

Une idée de comment corriger/modifier ce code ?

(3.4.0 était https://github.com/webdriverio/webdriverio/blob/1109adab9a5dbd1449fd035b20693d3c68d1d557/lib/launcher.js#L34)

Éditer
Les lignes 220-223 pourraient ressembler à ceci

            this.startInstance(schedulableCaps[0].specs, schedulableCaps[0].caps, schedulableCaps[0].cid)
            schedulableCaps[0].availableInstances--
            schedulableCaps[0].runningInstances++
            schedulableCaps[0].specs = []

(passer toutes les spécifications à l'instance, puis rendre toutes les spécifications vides afin que le filtre avec specs.length puisse être appliqué)

Modifier 2
Cela m'a pris environ une heure ou plus, mais soyez prudent lorsque vous utilisez process.send avec l'ensemble de l'objet specs. Dans mon cas, la longueur est > 100, ce qui donne un message plus gros que ce qu'IPC peut gérer (voir par exemple cat /proc/sys/kernel/msgmax (http://www.linuxinsight.com/proc_sys_kernel_msgmax.html).
(idée possible : http://stackoverflow.com/q/24582213/1902598)
(En parlant de cette ligne https://github.com/webdriverio/webdriverio/blob/master/lib/launcher.js#L291)

Si quelqu'un veut savoir comment implémenter une option --grep :

helpers.js

let path = require('path'),
    fs = require('fs');

let merge = require('deepmerge'),
    glob = require('glob');

module.exports = {
    /**
     * <strong i="8">@returns</strong> {string|undefined}
     */
    options () {
        for (let option of process.argv) {  
            let [key, value] = option.split('=');

            if (key === name) {
                return value;
            }
        }
    },

    /**
     * { <suite>: [ <files> ] }
     *
     * <strong i="9">@param</strong> {string} directory
     * <strong i="10">@param</strong> {string} additional
     * <strong i="11">@returns</strong> {Object}
     */
    suites (directory, additional = {}) {
        let files = fs.readdirSync(directory),
            cases = {};

        let grep = this.options('--grep');

        files.forEach(suite => {
            let files = path.join(directory, suite, '**/*.js'),
                debug = false;

            if (process.env.NODE_DEBUG) {
                debug = true;
            }

            files = glob.sync(files, {
                cache: true,
                debug
            });

            cases[suite] = files.filter(file => {
                if (grep) {
                    let match = new RegExp(grep);

                    if (grep && match.test(file)) {
                        return file;
                    }
                } else {
                    return file;
                }
            });
        });

        return this.extend(cases, additional);
    }

    /**
     * <strong i="12">@param</strong> {Object} x
     * <strong i="13">@param</strong> {Object} y
     * <strong i="14">@returns</strong> {Object}
     */
    extend (x, y) {
        return merge(...arguments);
    }
}

wdio.config.js

let helpers = require('./helpers');

exports.config = {
    suites: helpers.suites('tests')
}

essais

     foo
         test_1.js
         test_2.js

package.json

{
    "scripts": {
        "test"   : "wdio wdio.config.js",
    },

    "dependencies": {
        "deepmerge"           : "^0.2.10",
        "glob"                : "^7.0.5",
        "webdriverio"         : "^4.1.1",
        "wdio-spec-reporter"  : "^0.0.1",
        "wdio-mocha-framework": "^0.3.4",
    }
}

coquille

npm test -- --suite=foo --grep=test_1*;

Ce correctif va-t-il être mis dans la base de code principale ?

@wirsingj peut-être. J'espérais utiliser les frameworks internes pour le faire. Je n'ai pas enquêté là-dessus cependant.

@christian-bromann Cool, merci. J'ai trouvé que ce problème gênait également la prise en charge du débogage de wdio-cucumber-framework .. il ouvre un port de débogage pour chacun des processus enfants. :\

J'ai eu le même problème avec l'ouverture de plusieurs navigateurs. Tout le monde utilise-t-il toujours le travail de

Je viens de spécifier le fichier de fonctionnalités (en utilisant le concombre) pour le moment. Nous attendions de voir si ce correctif en ferait une version avant d'utiliser la solution la plus créative :)

Merci @wirsingj Je

@cheapaschips Nous utilisons le lanceur de test wdio-concombre en mode asynchrone.

des progrès sur cette question?

++1, un statut à ce sujet ?

pas vraiment de solution de contournement mais j'ai utilisé

wdio wdio.conf.js --spec "features/scenarios/test.feature" 

cela ne lancera que ce fichier, mais si vous utilisez des balises, vous n'aurez pas de chance et vous obtiendrez les navigateurs 1 à 1 de .features.

Dans wdio.conf.js vous pouvez définir une fonction pour specs :

specs: require('./specs-processor')(process.argv),

Dans mon cas:

const fs = require('fs');
const path = require('path');

const dir = require('node-dir'); // https://github.com/fshost/node-dir


/**
 * Based on https://github.com/webdriverio/cucumber-boilerplate/blob/master/src/tagProcessor.js
 * If specific tags are specified, and match the filename of a feature file, only load that/those feature files
 * Workaround for https://github.com/webdriverio/wdio-cucumber-framework/issues/8
 *
 * <strong i="11">@param</strong>  {Object} consoleArguments The arguments to parse from the console
 * <strong i="12">@return</strong> {Array}                   The specs to process
 */
module.exports = (consoleArguments) => {
  // This is required since this file is not parsed with Babel

  'use strict';

  let specs = [];

  let files = dir.files(path.join(__dirname, 'features'), {sync: true});

  consoleArguments.forEach((val) => {
    if (val.indexOf('--tags=') === 0) {
      const tags = val.replace('--tags=', '').split(',');

      tags.forEach((tagWithAtSymbol) => {
        const tag = tagWithAtSymbol.replace(/^@/, '');
        files.forEach((file) => {
          if (new RegExp(path.sep + tag + '\.feature$').test(file)) {
            file = file.replace(__dirname, '.');
            specs.push(file);
          }
        });
      });
    } else if (val.indexOf('--specs=') === 0) {
      specs = specs.concat(val.replace('--specs=', '').split(','));
    }
  });

  if (specs.length === 0) {
    specs.push('./features/**/*.feature');
  }

  return specs;
};

Ce que je fais ici vérifier si une balise demandée a un fichier .feature correspondant — donc si vous voulez @foo et que foo.feature existe, définissez specs sur juste foo.feature (ou plusieurs fichiers de fonctionnalités pour plusieurs balises demandées). Vous pouvez aller plus loin et rechercher dans les fichiers .feature les balises demandées et ne charger que celles-ci ; cela résoudrait réellement ce bogue, je suppose. Dans mon cas, lorsque j'ai une balise qui ne correspond pas au nom de fichier du fichier de fonctionnalités, je déclare le fichier spec explicitement, par exemple wdio --spec=./features/foo.feature --tags=@wip

Des avancées sur cette question ?

Est-ce que cela va être corrigé dans wdio ou wdio-concumber-framework ?

Finalement oui, mais cela n'a pas une priorité élevée puisque wdio prend également en charge des outils pour sélectionner des spécifications uniques

@christian-bromann Y a-t-il un moyen de contourner cela ?? ou va-t-il être corrigé dans wdio-concumber-framework ??

Quelqu'un a-t-il une mise à jour à ce sujet ou une solution aux problèmes initiaux ou j'ai besoin d'attendre que https://github.com/AlexGalichenko/webdriver-io-cucumber/issues/13 soit corrigé ?.

+1 sur ce problème, super ennuyeux

Nous essaierons de trouver un moyen de contourner cela dans la v5

Une solution de contournement est-elle disponible à ce jour pour ce problème ?

non, vous pouvez définir des suites et des spécifications avec --spec ou --suite , alors assurez-vous de ne définir que les tests que vous voulez réellement exécuter

J'espère voir bientôt une solution pour exécuter les fichiers à l'aide de balises. Face à beaucoup de problèmes en raison de ce problème.

Vous pouvez utiliser d'autres utilitaires que des balises pour structurer vos tests, je ne vois même pas cela comme un problème majeur ou urgent.

Je viens d'essayer cela, et cela a semblé fonctionner la première fois dans le wdio.conf.js ... a probablement besoin d'un peu de travail, mais semble ok

const TagExpressionParser = require('cucumber-tag-expressions').TagExpressionParser
const tagParser = new TagExpressionParser()
...
const cucumberTags = process.env.TAGS != null ? process.env.TAGS : 'not <strong i="7">@x</strong>'
....
const expressionNode = tagParser.parse(cucumberTags)
const filesWithTags = glob.sync('./features/**/*.feature').map((file) => {
  const content = fs.readFileSync(file, 'utf8')
  if (content.length > 0) {
    const tagsInFile = content.match(/(@\w+)/g) || []
    if (expressionNode.evaluate(tagsInFile)) {
      return file
    }
  }
  return null
}).filter(x => x != null)

...

exports.config = {
  specs: filesWithTags,
...
}

Vous pouvez transmettre les balises en tant que variable d'environnement comme ceci :
TAGS="<strong i="11">@smoke</strong> and @dev" ./node_modules/.bin/wdio

Les balises sont le moyen le plus efficace de filtrer nos tests à des fins multiples (par exemple, caractériser un test s'il s'agit de fumée ou de régression, s'il couvre appX ou appY, s'il couvre featureX ou featureY et une autre featureZ. Quels sont les autres non options de marquage pour que quelqu'un puisse caractériser pour plus d'un aspect ses tests et être capable de les déclencher/filtrer pour l'exécution ?

Je suis confronté au même problème.
Y a-t-il une mise à jour sur le moment où nous allons résoudre ce problème ?

Y a-t-il une mise à jour sur le moment où nous allons résoudre ce problème ?

@ashishkhanna999 n'hésitez pas à proposer un correctif. Ce n'est pas anodin, c'est pourquoi il n'a pas été touché.

Que diriez-vous de quelque chose comme ça https://github.com/webdriverio/webdriverio/issues/2859#issuecomment -492802582 ?

J'ai réussi à faire un travail très simple autour. C'est un peu fou mais ça marche ! Nous en avions besoin car la génération inutile d'instances Chrome ajoutait trop de temps à notre temps de déploiement, car nous voulions exécuter un sous-ensemble de tests après le déploiement sans avoir à les dupliquer dans un fichier de fonctionnalités de post-déploiement spécifique. Tout ce que je fais, c'est parcourir tous les fichiers de fonctionnalités, extraire les balises de chaque fichier (tous nos scénarios ne sont pas balisés, nous avions donc besoin de quelque chose d'un peu plus complet, c'est pourquoi nous parcourons les balises « cueillette de cerises » de chaque fichier), puis reconstruisons le fichiers dans un autre répertoire avec la fonctionnalité correcte context et background . J'ai un conditionnel sur le champ "specs" dans wdio.conf.js pour récupérer le chemin si le site est en cours de déploiement, sinon il utilise le chemin par défaut.

specs: [
        helpers.cherryPickTags(featuresDir, taggedFeaturesDir, this_is_running_during_a_deployment) ? "./"+taggedFeaturesDir+"**/*.feature" : "./"+featuresDir+"**/*.feature"
    ],
var path = require("path");
var fs  = require('fs');

module.exports = {
    cherryPickTags:function(featuresDir, taggedFeaturesDir, this_is_running_during_a_deployment){  
        if(this_is_running_during_a_deployment)
        {
            if (!fs.existsSync(taggedFeaturesDir)) {
                console.log("Cherry picking tags from feature files...");
                fs.mkdirSync(taggedFeaturesDir);
                fs.readdir(featuresDir, (err, files) => {
                  files.forEach(file => {
                        fs.readFile(featuresDir+file, 'utf8', function(err, contents) {
                            if(contents != null){
                                var featureBody = contents.replace(/Scenario:.+|Scenario Outline:.+/s,"");
                                featureBody = featureBody.replace("@postDeploymentTests", "");
                                var tags = contents.replace(/\r\n/g, "\n").match(/@postDeploymentTests.+?^\n|@postDeploymentTests.+$/msg)
                                if(tags != null)
                                {
                                    featureBody = featureBody + tags.join("\n");
                                    fs.writeFile(taggedFeaturesDir+file, featureBody, (err) => {
                                      if (err) throw err;
                                      console.log('Feature file with tags created: ' + file);
                                    });
                                }

                            }
                        });
                  });
                });
             }
        } 
        return this_is_running_during_a_deployment;
    }
}

Si vous comptez l'utiliser, n'oubliez pas de modifier les entrées regex en votre balise spécifique.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

halfzebra picture halfzebra  ·  3Commentaires

imranazad picture imranazad  ·  3Commentaires

sarahdayan picture sarahdayan  ·  4Commentaires

davidsoderberg picture davidsoderberg  ·  4Commentaires

briancullinan picture briancullinan  ·  4Commentaires