web-dev-qa-db-fra.com

Le test de l'interface utilisateur codée est lent dans l'attente d'un thread d'interface utilisateur

J'ai ajouté des tests d'interface utilisateur codés à ma solution ASP.NET MVC dans Visual Studio 2013. J'étais consterné de voir la lenteur d'exécution des tests; chaque page reste pendant une minute ou plus avant que la machine de test ne se réveille et commence à remplir les champs du formulaire.

Après quelques expériences (notamment en désactivant SmartMatch), j’ai découvert qu’appeler simplement

Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.Disabled;

résout le problème. Mais, comme prévu, le test échoue fréquemment car le thread d'interface utilisateur n'est pas prêt pour que la machine de test puisse interagir avec les contrôles du formulaire.

Appel

Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.UIThreadOnly;

effectue le test de manière fiable, même s’il est lent.

Des pensées ou des suggestions? Tout espoir que quelqu'un puisse avoir un aperçu de la magie incorporée dans les machines WaitForReady? Existe-t-il d'autres paramètres liés à WaitForReady que je peux manipuler en plus de WaitForReadyLevel?

24

Après un peu d'expérimentation, j'ai élaboré une combinaison de paramètres qui permettait à mes tests d'interface utilisateur codés de fonctionner de manière fiable à toute vitesse, plus rapidement que je ne pouvais interagir manuellement avec le site Web.

Remarque: la "documentation" pertinente (si vous appelez un blog "documentation") peut être trouvée ici:

L'astuce nécessite plusieurs modifications aux paramètres de lecture par défaut:

  • La définition de WaitForReadyLevel = WaitForReadyLevel.Disabled permet au test de fonctionner à pleine vitesse. Mais il désactive également la magie (lente!) Qui attend qu'il soit possible d'interagir en toute sécurité avec les contrôles de la page.

  • Définir MaximumRetryCount et associer un gestionnaire d'erreurs traite la plupart des erreurs résultant de la désactivation de la magie "attendre pour prêt". Comme j'ai ajouté Sleep à une seconde dans la logique de nouvelle tentative, cette valeur correspond effectivement au nombre de secondes pendant lesquelles je suis prêt à attendre que la page se charge et devienne réactive.

  • Apparemment, l’échec de la recherche du contrôle sous test n’est pas l’une des erreurs gérées par le mécanisme de traitement des erreurs/nouvelle tentative. Si le chargement de la nouvelle page prend plus de quelques secondes et que le test recherche un contrôle qui n'existe pas jusqu'au chargement de la nouvelle page, le test ne parvient pas à trouver le contrôle et échoue. Le paramétrage de ShouldSearchFailFast = false résout ce problème en vous laissant le délai d’expiration pour le chargement de votre page.

  • Le paramétrage de DelayBetweenActions = 500 semble résoudre un problème que je vois parfois lorsque l’interface utilisateur manque un clic de bouton qui se produit immédiatement après le chargement d’une page. La machine de test semble penser que le bouton a été cliqué, mais la page Web ne répond pas.

  • La "documentation" indique que le délai d'attente de recherche par défaut est de 3 minutes, mais qu'il s'agit en réalité d'un délai supérieur à 10 minutes. J'ai donc explicitement défini SearchTimeout sur 1 seconde (1000 ms).

Pour conserver tout le code au même endroit, j'ai créé une classe contenant le code utilisé par tous les tests. MyCodedUITests.StartTest() est appelé par la méthode [TestInitialize] dans chacune de mes classes de test.

Ce code ne devrait en réalité être exécuté qu'une seule fois pour tous les tests (au lieu d'une fois par test), mais je ne pouvais pas trouver un moyen de faire en sorte que les appels Playback.PlaybackSettings fonctionnent dans les routines [AssemblyInitialization] ou [ClassInitialization].

/// <summary> A class containing Coded UI Tests. </summary>
[CodedUITest]
public class UI_Tests
{
    /// <summary> Common initialization for all of the tests in this class. </summary>
    [TestInitialize]
    public void TestInit()
    {
        // Call a common routine to set up the test
        MyCodedUITests.StartTest();
    }

    /// <summary> Some test. </summary>
    [TestMethod]
    public void SomeTest()
    {
        this.UIMap.Assert_HomePageElements();
        this.UIMap.Recorded_DoSomething();
        this.UIMap.Assert_FinalPageElements();
    }
}


/// <summary> Coded UI Test support routines. </summary>
class MyCodedUITests
{
    /// <summary> Test startup. </summary>
    public static void StartTest()
    {
        // Configure the playback engine
        Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.Disabled;
        Playback.PlaybackSettings.MaximumRetryCount = 10;
        Playback.PlaybackSettings.ShouldSearchFailFast = false;
        Playback.PlaybackSettings.DelayBetweenActions = 500;
        Playback.PlaybackSettings.SearchTimeout = 1000;

        // Add the error handler
        Playback.PlaybackError -= Playback_PlaybackError; // Remove the handler if it's already added
        Playback.PlaybackError += Playback_PlaybackError; // Ta dah...
    }

    /// <summary> PlaybackError event handler. </summary>
    private static void Playback_PlaybackError(object sender, PlaybackErrorEventArgs e)
    {
        // Wait a second
        System.Threading.Thread.Sleep(1000);

        // Retry the failed test operation
        e.Result = PlaybackErrorOptions.Retry;
    }
}
38

Une interface utilisateur codée recherche les contrôles à l'écran et cette recherche est assez rapide en cas de succès. Cependant, si la recherche échoue, l'interface utilisateur codée a une autre tentative en utilisant une méthode de "correspondance intelligente" et cela peut être lent. Pour éviter que l'interface utilisateur codée ne recourt à la correspondance intelligente, la méthode de base consiste à supprimer ou à simplifier les éléments de recherche susceptibles de changer d'une exécution à l'autre.

Ce blog Microsoft donne de nombreuses explications sur ce qui se passe et comment le corriger. L’exemple ci-dessous montre une accélération de 30 à 8 secondes en modifiant une chaîne de recherche de

Name EqualsTo “Sales order‬ (‎‪1‬ - ‎‪ceu‬)‎‪ - ‎‪‪‪Sales order‬: ‎‪SO-101375‬‬, ‎‪‪Forest Wholesales”

à

Name Contains “Sales order‬ (‎‪1‬ - ‎‪ceu‬)‎‪ - ‎‪‪‪Sales order‬: ‎‪SO”
6
AdrianHHH

On dirait qu'il est capturé à partir de l'outil dynamique Microsoft. Veuillez vérifier la longueur de la chaîne capturée à partir de l'outil d'inspection. Vous allez trouver un personnage caché. il suffit de commander (1 - ceu). Sinon, déplacez simplement le curseur de "(" à ")". Vous constaterez que le curseur ne bouge pas lorsque vous appuyez sur la flèche droite.

0
Sipu Kkc