6
votes

Comment mettre à jour automatiquement chromeDriver et geckoDriver dans le sélénium

J'ai une configuration de grille de sélénium avec plusieurs machines à nœuds, où je télécharge manuellement chromeDriver et geckoDriver sur toutes les machines à nœuds de sélénium et les utilise respectivement pour les navigateurs Chrome et Firefox.

Maintenant, ici, les navigateurs Chrome et Firefox (sur toutes les machines à nœuds de sélénium) sont définis sur 'Mise à jour automatique' (ce qui est nécessaire car je veux que mon application soit toujours testée sur les dernières versions de navigateur), à cause de cette les navigateurs de mes machines à nœuds sont mis à jour plus souvent et comme les mises à jour des pilotes respectifs sont un processus manuel, cela m'oblige à me connecter à chaque machine à nœuds sélénium et à les mettre à jour manuellement .

Ce processus peut-il être automatisé?

PS: Je sais que la grille de sélénium dockerisée peut être utilisée pour récupérer / extraire les dernières images du navigateur et leurs pilotes, mais le passage d'une grille de sélénium traditionnelle à une grille de sélénium dockerisée est une autre chose et prendra un certain temps à mettre en œuvre.


1 commentaires

Je ne sais pas quelle approche vous avez finalement adoptée, je suis dans une situation similaire et j'ai trouvé une bibliothèque qui gère le pilote automatiquement: github. com / bonigarcia / webdrivermanager . Je n'ai pas encore exploré cette approche, mais je voulais vous envoyer une note si cela peut vous aider.


6 Réponses :


6
votes

Je dirais que votre approche actuelle n'est pas une approche réalisable. De nouvelles versions de navigateurs sont publiées sans aucune considération pour Selenium (ou tout autre pilote). Dès qu'une nouvelle mise à jour du navigateur est publiée, il y a de fortes chances qu'il n'y ait AUCUN pilote existant qui fonctionne avec cette version. Il faut souvent des jours aux équipes Selenium pour publier des pilotes mis à jour correspondant à la dernière version d'un navigateur.

Et comme vous mettez à jour automatiquement vos navigateurs, vous risquez alors de casser automatiquement vos tests Selenium jusqu'à ce qu'une nouvelle version de pilote soit publiée, ou jusqu'à ce que vous rétrogradiez les navigateurs.

Maintenant, vous pouvez être d'accord avec cela, et vous pouvez désactiver les tests d'un navigateur jusqu'à ce que les pilotes Selenium les plus récents fonctionnent avec la version la plus récente du navigateur. Si tel est le cas, voici quelques solutions:

1) Si vous utilisez C #, stockez vos pilotes dans la solution de test sous forme de package Nuget, ou dans une dépendance dossier. Ensuite, ayez la référence d'automatisation de ce pilote, peu importe où il s'exécute. Lorsque vous devez mettre à jour le pilote, vous n'avez littéralement besoin de le mettre à jour qu'à un seul endroit et d'enregistrer les modifications. Toutes les machines clientes, par le biais de votre processus CI, extrairont le dernier code, qui inclut ce nouveau pilote.

2) Si, pour une raison quelconque, vous ne voulez pas que le pilote soit dans votre projet en tant que package Nuget ou dépendance enregistrée manuellement, puis demandez à votre CI de gérer le processus de mise à jour. Pointez votre code d'automatisation vers un pilote situé dans un répertoire commun sur la machine cliente sur laquelle il s'exécute actuellement -> partout où votre machine stocke les dépendances après les avoir téléchargées. Par exemple; le téléchargement de fichiers de sélénium via la console sur une machine Windows les placera quelque part dans% APPDATA% "C: \ Users \ xxxxxx \ AppData \ Roaming \ npm \ node_modules". C'est là que doit se trouver votre solution de test.

Ensuite, dans vos scripts CI, avant d'exécuter des tests, téléchargez le dernier pilote. La syntaxe est presque la même, sinon identique entre les noyaux Windows et Linux / Unix. Cela suppose que vous avez installé npm.

npm install -g selenium

Si vous avez déjà la dernière version, rien ne se passera. Si vous ne le faites pas, le dernier pilote sera téléchargé par votre script CI avant d'exécuter les tests. Ensuite, votre solution de test pointera vers où le pilote est stocké sur le client, et elle utilisera automatiquement le pilote le plus récent.


3 commentaires

Merci pour la réponse élaborée. Appréciez votre temps. Ici, j'exécute mes tests via jenkins, donc l'architecture / le flux est comme jenkins (déclenchement de la suite de sélénium) -> machine esclave jenkins (tirant le dépôt qa contenant des tests, les exécutant via gradle / maven) -> machine de hub de sélénium -> machines de nœuds de sélénium (ayant geckodriver / chromedriver) Compte tenu de l'architecture ci-dessus, laissez-moi réfléchir aux solutions ci-dessus,


# 1 suggère d'empaqueter les pilotes (chrome / gecko) dans le repo de tests, si je le fais, il restera chez mon esclave jenkins car jenkins slave est la machine qui tire qa repo, mais je veux que ces pilotes existent sur des machines à nœuds de sélénium. Donc, empaqueter les pilotes avec git / nuget manager ne m'aidera pas dans mon cas (Cependant, conserver ces pilotes dans un dossier partagé, qui peut être accessible par tous les nœuds de sélénium, puis mettre à jour manuellement les pilotes dans le dossier partagé une fois les nouveaux pilotes publiés, fonctionnera, mais ce sera encore une action manuelle)


# 2 suggère d'utiliser NPM pour mettre à jour selenium / chromedriver / geckodriver (comme npm install chromedriver / npm install geckodriver) avant d'exécuter des tests via jenkins. Je dois exécuter ces commandes spécifiquement sur les nœuds de sélénium en les rendant esclaves de jenkins (c'est-à-dire que la machine à nœuds de sélénium doit agir comme esclave de jenkins afin que je puisse exécuter des commandes sur eux), mais NPM serait la condition préalable à l'installation sur chaque machine à nœuds de sélénium . Eh bien, je vais essayer ces deux options et je verrai ce qui me convient le plus.



0
votes

Le problème a maintenant été résolu avec le module webdrivermanager de ici

< gagnantDescription :

Module Python pour faciliter le téléchargement et le déploiement des binaires WebDriver. Les classes de ce module peuvent être utilisées pour rechercher et télécharger automatiquement la dernière version (ou une version spécifique) d'un binaire WebDriver, puis l'extraire et le placer en le copiant ou en le liant symboliquement à l'emplacement où Selenium ou d'autres outils devraient pouvoir pour le trouver ensuite.

J'espère que ça aide !!!


0 commentaires

-1
votes

vous pouvez utiliser ansible ou puppet pour prendre le package de mise à jour sur tout le nœud


1 commentaires

Si vous pouviez mieux expliquer, comment mettre à jour Chrome et Firefox de manière étape par étape. Veuillez revoir cette question pour savoir comment rédiger une bonne réponse. stackoverflow.com/help/how-to-answer



0
votes

Je sais que c'est une question un peu ancienne, mais j'ai pensé que cela pourrait également être utile aux gens: https://github.com/rosolko/WebDriverManager.Net . C'est un package Nuget ( https://www.nuget.org/packages/WebDriverManager/ ) qui semble résoudre le problème en utilisant .NET.


0 commentaires

0
votes

Le premier @Asyranok a raison , même lorsque le code de mise à jour automatique implémenté ne fonctionnera pas 100% du temps. Cependant, pour beaucoup d’entre nous, ces temps d’interruption occasionnels sont «ok» tant que ce n’est que quelques jours.

J'ai trouvé que la mise à jour manuelle des serveurs X tous les quelques mois était incroyablement irritante et tant qu'il y en a instructions bien écrites sur le site Web de sélénium sur la façon de "mettre à jour automatiquement" le pilote que je n'ai pas encore vu une implémentation non-bibliothèque de ce guide disponible.

Ma réponse est spécifique au C #, pour ce langage, la solution généralement suggérée est de utilisez NuGet pour extraire automatiquement le dernier pilote, cela pose deux problèmes:

  1. Vous devez déployer à la fréquence de mise à jour de Chrome (la plupart des entreprises ne sont pas encore là, nous ne le sommes pas encore) ou votre application sera "cassée" pendant le temps entre la mise à jour de Chrome et votre "nouvelle" version de le déploiement de l'application, et encore une fois, ce n'est que si vous publiez selon un calendrier, si vous libérez ad-hoc, vous devrez passer par une série d'étapes manuelles pour mettre à jour, construire, publier, etc. pour que votre application fonctionne à nouveau.

  2. Vous avez besoin (généralement, sans a work around ) pour extraire manuellement le dernier chromedrive de NuGet, encore une fois un processus manuel.

Ce qui serait bien serait ce que python a et @leminhnguyenHUST suggère qui utilise une bibliothèque qui tirera automatiquement le dernier chromedriver lors de l'exécution. J'ai regardé autour de moi et je n'ai encore rien trouvé pour C # qui fasse cela, alors j'ai décidé de lancer le mien et de l'intégrer dans mon application:

//This is a very poor way of determining if I "need" to update the chromedriver,     
//however I've yet to figure out a better way of doing this...
try
{
    using (var chromeDriver = SetupChromeDriver())
    {
        chromeDriver.Navigate().GoToUrl("www.google.com");
        chromeDriver.Quit();
    }
}
catch
{
    DownloadLatestVersionOfChromeDriver();
}

Ensuite, généralement, je Je vais coller cette invocation très hacky au début de mon application pour appeler cette fonctionnalité et m'assurer que le dernier chromedriver est disponible pour mon application:

public void DownloadLatestVersionOfChromeDriver()
{
    string path = DownloadLatestVersionOfChromeDriverGetVersionPath();
    var version = DownloadLatestVersionOfChromeDriverGetChromeVersion(path);
    var urlToDownload = DownloadLatestVersionOfChromeDriverGetURLToDownload(version);
    DownloadLatestVersionOfChromeDriverKillAllChromeDriverProcesses();
    DownloadLatestVersionOfChromeDriverDownloadNewVersionOfChrome(urlToDownload);
}

public string DownloadLatestVersionOfChromeDriverGetVersionPath()
{
    //Path originates from here: https://chromedriver.chromium.org/downloads/version-selection            
    using (RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe"))
    {
        if (key != null)
        {
            Object o = key.GetValue("");
            if (!String.IsNullOrEmpty(o.ToString()))
            {
                return o.ToString();
            }
            else
            {
                throw new ArgumentException("Unable to get version because chrome registry value was null");
            }
        }
        else
        {
            throw new ArgumentException("Unable to get version because chrome registry path was null");
        }
    }
}

public string DownloadLatestVersionOfChromeDriverGetChromeVersion(string productVersionPath)
{
    if (String.IsNullOrEmpty(productVersionPath))
    {
        throw new ArgumentException("Unable to get version because path is empty");
    }

    if (!File.Exists(productVersionPath))
    {
        throw new FileNotFoundException("Unable to get version because path specifies a file that does not exists");
    }

    var versionInfo = FileVersionInfo.GetVersionInfo(productVersionPath);
    if (versionInfo != null && !String.IsNullOrEmpty(versionInfo.FileVersion))
    {
        return versionInfo.FileVersion;
    }
    else
    {
        throw new ArgumentException("Unable to get version from path because the version is either null or empty: " + productVersionPath);
    }
}

public string DownloadLatestVersionOfChromeDriverGetURLToDownload(string version)
{
    if (String.IsNullOrEmpty(version))
    {
        throw new ArgumentException("Unable to get url because version is empty");
    }

    //URL's originates from here: https://chromedriver.chromium.org/downloads/version-selection
    string html = string.Empty;
    string urlToPathLocation = @"https://chromedriver.storage.googleapis.com/LATEST_RELEASE_" + String.Join(".", version.Split('.').Take(3));

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToPathLocation);
    request.AutomaticDecompression = DecompressionMethods.GZip;

    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    using (Stream stream = response.GetResponseStream())
    using (StreamReader reader = new StreamReader(stream))
    {
        html = reader.ReadToEnd();
    }

    if (String.IsNullOrEmpty(html))
    {
        throw new WebException("Unable to get version path from website");
    }

    return "https://chromedriver.storage.googleapis.com/" + html + "/chromedriver_win32.zip";
}

public void DownloadLatestVersionOfChromeDriverKillAllChromeDriverProcesses()
{
    //It's important to kill all processes before attempting to replace the chrome driver, because if you do not you may still have file locks left over
    var processes = Process.GetProcessesByName("chromedriver");
    foreach (var process in processes)
    {
        try
        {
            process.Kill();
        }
        catch
        {
            //We do our best here but if another user account is running the chrome driver we may not be able to kill it unless we run from a elevated user account + various other reasons we don't care about
        }
    }
}

public void DownloadLatestVersionOfChromeDriverDownloadNewVersionOfChrome(string urlToDownload)
{
    if (String.IsNullOrEmpty(urlToDownload))
    {
        throw new ArgumentException("Unable to get url because urlToDownload is empty");
    }

    //Downloaded files always come as a zip, we need to do a bit of switching around to get everything in the right place
    using (var client = new WebClient())
    {
        if (File.Exists(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.zip"))
        {
            File.Delete(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.zip");
        }

        client.DownloadFile(urlToDownload, "chromedriver.zip");

        if (File.Exists(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.zip") && File.Exists(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.exe"))
        {
            File.Delete(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.exe");
        }

        if (File.Exists(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.zip"))
        {
            System.IO.Compression.ZipFile.ExtractToDirectory(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.zip", System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));
        }
    }
}

Je suis sûr que cela pourrait être amélioré de manière significative, mais jusqu'à présent, cela a fonctionné pour moi.

Remarque: Publication croisée ici


0 commentaires

0
votes

Une option pour la solution basée sur Java est le Bonigarcia Webdrivermanager. On dirait qu'il a un support intégré pour le pilote Web distant, en utilisant ce gestionnaire de lecteur est capable de télécharger les derniers navigateurs sur le Hub de la grille de sélénium. Consultez ce message.


0 commentaires