Ejemplo n.º 1
0
        private void TouchAndMoveOut(QueryEx element)
        {
            var rect = _app.WaitForElement(element).Single().Rect;

            _app.DragCoordinates(rect.X + 10, rect.Y + 10, rect.Right + 10, rect.Y + 10);
        }
Ejemplo n.º 2
0
        [Timeout(700000)]         // Adjust this timeout based on average test run duration
        public async Task RunRuntimeTests()
        {
            Run("SamplesApp.Samples.UnitTests.UnitTestsPage");

            IAppQuery AllQuery(IAppQuery query)
            // .All() is not yet supported for wasm.
            => AppInitializer.GetLocalPlatform() == Platform.Browser ? query : query.All();

            var runButton        = new QueryEx(q => AllQuery(q).Marked("runButton"));
            var failedTestsCount = new QueryEx(q => AllQuery(q).Marked("failedTestCount"));
            var failedTests      = new QueryEx(q => AllQuery(q).Marked("failedTests"));
            var runningState     = new QueryEx(q => AllQuery(q).Marked("runningState"));
            var runTestCount     = new QueryEx(q => AllQuery(q).Marked("runTestCount"));

            bool IsTestExecutionDone()
            => runningState.GetDependencyPropertyValue("Text")?.ToString().Equals("Finished", StringComparison.OrdinalIgnoreCase) ?? false;

            _app.WaitForElement(runButton);

            _app.FastTap(runButton);

            var lastChange = DateTimeOffset.Now;
            var lastValue  = "";

            while (DateTimeOffset.Now - lastChange < TestRunTimeout)
            {
                var newValue = runTestCount.GetDependencyPropertyValue("Text")?.ToString();

                if (lastValue != newValue)
                {
                    lastChange = DateTimeOffset.Now;
                }

                await Task.Delay(TimeSpan.FromSeconds(.5));

                if (IsTestExecutionDone())
                {
                    break;
                }
            }

            if (!IsTestExecutionDone())
            {
                Assert.Fail("A test run timed out");
            }

            var count = failedTestsCount.GetDependencyPropertyValue("Text").ToString();

            if (count != "0")
            {
                var tests = failedTests.GetDependencyPropertyValue <string>("Text")
                            .Split(new char[] { '§' }, StringSplitOptions.RemoveEmptyEntries)
                            .Select((x, i) => $"\t{i + 1}. {x}\n")
                            .ToArray();

                var details = _app.Marked("failedTestDetails").GetDependencyPropertyValue("Text");

                Assert.Fail(
                    $"{tests.Length} unit test(s) failed.\n\tFailing Tests:\n{string.Join("", tests)}\n\n---\n\tDetails:\n{details}");
            }

            TakeScreenshot("Runtime Tests Results", ignoreInSnapshotCompare: true);
        }
Ejemplo n.º 3
0
        [Timeout(500000)]         // Adjust this timeout based on average test run duration
        public async Task RunBenchmarks()
        {
            Run("Benchmarks.Shared.Controls.BenchmarkDotNetTestsPage");

            IAppQuery AllQuery(IAppQuery query)
            // .All() is not yet supported for wasm.
            => AppInitializer.GetLocalPlatform() == Platform.Browser ? query : query.All();

            var runButton        = new QueryEx(q => AllQuery(q).Marked("runButton"));
            var runStatus        = new QueryEx(q => AllQuery(q).Marked("runStatus"));
            var runCount         = new QueryEx(q => AllQuery(q).Marked("runCount"));
            var benchmarkControl = new QueryEx(q => AllQuery(q).Marked("benchmarkControl"));

            bool IsTestExecutionDone()
            {
                try
                {
                    var text = runStatus.GetDependencyPropertyValue("Text")?.ToString();
                    var r2   = text?.Equals("Finished", StringComparison.OrdinalIgnoreCase) ?? false;

                    Console.WriteLine($"IsTestExecutionDone: {text} {r2}");

                    return(r2);
                }
                catch
                {
                    Console.WriteLine("Skip IsTestExecutionDone");

                    // Skip exceptions as they may be timeouts
                    return(false);
                }
            }

            _app.WaitForElement(runButton);

            TakeScreenshot("Begin", ignoreInSnapshotCompare: true);

            _app.FastTap(runButton);

            var lastChange = DateTimeOffset.Now;
            var lastValue  = "";

            while (DateTimeOffset.Now - lastChange < TestRunTimeout)
            {
                try
                {
                    if (IsTestExecutionDone())
                    {
                        break;
                    }

                    var newValue = runCount.GetDependencyPropertyValue("Text")?.ToString();

                    if (lastValue != newValue)
                    {
                        Console.WriteLine($"Loop: Test changed now:{DateTimeOffset.Now} lastChange: {lastChange}");

                        lastChange = DateTimeOffset.Now;
                        TakeScreenshot($"Run {newValue}", ignoreInSnapshotCompare: true);
                    }
                }
                catch (Exception e)
                {
                    // Skip exceptions as they may be timeouts
                }

                await Task.Delay(TimeSpan.FromSeconds(.5));

                Console.WriteLine($"Loop: now:{DateTimeOffset.Now} lastChange: {lastChange}");
            }

            if (!IsTestExecutionDone())
            {
                Assert.Fail("A test run timed out");
            }

            var finalFile = ArchiveResults(benchmarkControl);

            TestContext.AddTestAttachment(finalFile, "benchmark-results.zip");

            TakeScreenshot("Runtime Tests Results", ignoreInSnapshotCompare: true);
        }
Ejemplo n.º 4
0
 public ScrollContextTracker(QueryEx currentContext)
 {
     _previousContext   = _findScrollContext;
     _findScrollContext = currentContext;
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Attempts to find an element matching the <see cref="to"/> query, scrolling UP if necessary
 /// </summary>
 /// <param name="app">The application</param>
 /// <param name="to">The query that indicates the element that is searched for"/></param>
 /// <param name="timeout">[Optionnal] An explicit value for the timeout. If not specified, the default timeout  will be used.</param>
 /// <returns>A query pointing to the resulting element if it was found</returns>
 public static QueryEx FindUpwards(this IApp app, QueryEx to, TimeSpan?timeout = null)
 {
     return(app.FindInternal(to, direction: FindScrollDirection.Up, timeOut: timeout));
 }
Ejemplo n.º 6
0
        public void ValidateShape(string shapeName, PixelTolerance?tolerance = null)
        {
            Run("UITests.Windows_UI_Xaml_Shapes.Basic_Shapes", skipInitialScreenshot: true);

            var ctrl = new QueryEx(q => q.Marked("_basicShapesTestRoot"));
            var expectedDirectory = Path.Combine(
                TestContext.CurrentContext.TestDirectory,
                "Windows_UI_Xaml_Shapes/Basics_Shapes_Tests_EpectedResults");
            var actualDirectory = Path.Combine(
                TestContext.CurrentContext.WorkDirectory,
                nameof(Windows_UI_Xaml_Shapes),
                nameof(Basics_Shapes_Tests),
                shapeName);

            tolerance = tolerance ?? (new PixelTolerance()
                                      .WithColor(132) // We are almost only trying to detect edges
                                      .WithOffset(3, 3, LocationToleranceKind.PerPixel)
                                      .Discrete(2));

            var failures = new List <(string test, Exception error)>();
            // To improve performance, we run all test for a given stretch at once.
            var testGroups = _tests
                             .Where(t => t.StartsWith(shapeName))
                             .GroupBy(t => string.Join("_", t.Split(new[] { '_' }, 3, StringSplitOptions.RemoveEmptyEntries).Take(2)));

            foreach (var testGroup in testGroups)
            {
                ctrl.SetDependencyPropertyValue("RunTest", string.Join(";", testGroup));
                _app.WaitFor(() => !string.IsNullOrWhiteSpace(ctrl.GetDependencyPropertyValue <string>("TestResult")), timeout: TimeSpan.FromMinutes(1));
                var testResultsRaw = ctrl.GetDependencyPropertyValue <string>("TestResult");

                var testResults = testResultsRaw
                                  .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                                  .Select(line => line.Split(new[] { ';' }, 3, StringSplitOptions.RemoveEmptyEntries))
                                  .Where(line => line.Length == 3)
                                  .ToDictionary(
                    line => line[0],
                    line =>
                {
                    var testName  = line[0];
                    var isSuccess = line[1] == "SUCCESS";
                    var data      = Convert.FromBase64String(line[2]);

                    var target = Path
                                 .Combine(actualDirectory, testName + (isSuccess ? ".png" : ".txt"))
                                 .GetNormalizedLongPath();
                    var targetFile = new FileInfo(target);

                    targetFile.Directory.Create();
                    File.WriteAllBytes(target, data);
                    SetOptions(targetFile, new ScreenshotOptions {
                        IgnoreInSnapshotCompare = true
                    });
                    TestContext.AddTestAttachment(target, testName);

                    return(isSuccess
                                                                ? new Bitmap(new MemoryStream(Convert.FromBase64String(line[2])))
                                                                : new Exception(Encoding.UTF8.GetString(Convert.FromBase64String(line[2]))) as object);
                });

                foreach (var test in testGroup)
                {
                    try
                    {
                        var expected = new FileInfo(Path.Combine(expectedDirectory, $"{test}.png"));
                        if (!expected.Exists)
                        {
                            Assert.Fail($"Expected screenshot does not exists ({expected.FullName})");
                        }

                        if (!testResults.TryGetValue(test, out var testResult))
                        {
                            Assert.Fail($"No test result for {test}.");
                        }

                        if (testResult is Exception error)
                        {
                            Assert.Fail($"Test failed: {error.Message}");
                        }

                        using (var actual = (Bitmap)testResult)
                        {
                            var scale = _app.GetDisplayScreenScaling();
                            ImageAssert.AreAlmostEqual(expected, ImageAssert.FirstQuadrant, actual, ImageAssert.FirstQuadrant, scale, tolerance.Value);
                        }
                    }
                    catch (Exception e)
                    {
                        Console.Error.WriteLine(e);                         // Ease debug while reading log from CI
                        failures.Add((test, e));
                    }
                }
            }

            if (failures.Any())
            {
                throw new AggregateException(
                          $"Failed tests ({failures.Count} of {testGroups.Sum(g => g.Count())}):\r\n{string.Join("\r\n", failures.Select(t => t.test))}\r\n",
                          failures.Select(t => t.error));
            }
            else
            {
                Console.WriteLine($"All {testGroups.Sum(g => g.Count())} ran successfully.");
            }
        }
Ejemplo n.º 7
0
        private void TapSomewhereInElement(QueryEx element)
        {
            var rect = _app.WaitForElement(element).Single().Rect;

            _app.TapCoordinates(rect.X + 10, rect.Y + 10);
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Attempts to find an element matching the <see cref="to"/> query, scrolling up on
 /// the element matching the <see cref="within"/> query if necessary
 /// </summary>
 /// <param name="app">The application</param>
 /// <param name="to">The query that indicates the element that is searched for within <see cref="within"/></param>
 /// <param name="within">The query that indicates the element where any scrolling required to reach the element will occur</param>
 /// <param name="timeout">[Optionnal] An explicit value for the timeout. If not specified, the default timeout  will be used.</param>
 /// <returns>A query pointing to the resulting element if it was found</returns>
 public static QueryEx FindUpwardsWithin(this IApp app, Func <QueryEx, QueryEx> to, QueryEx within, TimeSpan?timeout = null)
 {
     return(app.FindUpwardsWithin(QueryExFactory.BlankQuery().Transform(to), within, timeout: timeout));
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Attempts to find an element marked with the given value, scrolling up on
 /// the element matching the <see cref="within"/> query if necessary
 /// </summary>
 /// <param name="app">The application</param>
 /// <param name="marked">The mark of the element that is searched for within <see cref="within"/></param>
 /// <param name="within">The query that indicates the element where any scrolling required to reach the element will occur</param>
 /// <param name="timeout">[Optionnal] An explicit value for the timeout. If not specified, the default timeout  will be used.</param>
 /// <returns>A query pointing to the resulting element if it was found</returns>
 public static QueryEx FindUpwardsWithin(this IApp app, string marked, QueryEx within, TimeSpan?timeout = null)
 {
     return(app.FindUpwardsWithin(q => q.Marked(marked), within));
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Attempts to find an element matching the <see cref="to"/> query, scrolling down on
        /// the element matching the <see cref="within"/> query if necessary
        /// </summary>
        /// <param name="app">The application</param>
        /// <param name="to">The query transform that indicates the element that is searched for within <see cref="within"/></param>
        /// <param name="within">The query that indicates the element where any scrolling required to reach the element will occur</param>
        /// <param name="timeout">[Optionnal] An explicit value for the timeout. If not specified, the default timeout  will be used.</param>
        /// <returns>A query pointing to the resulting element if it was found</returns>
        public static QueryEx FindWithin(this IApp app, Func <QueryEx, QueryEx> to, QueryEx within, TimeSpan?timeout = null)
        {
            var target = QueryExFactory.BlankQuery().Transform(to);

            return(app.FindInternal(target, within, timeOut: timeout));
        }
Ejemplo n.º 11
0
 public static QueryEx FindWithin(this IApp app, string marked, QueryEx within, TimeSpan?timeout = null)
 {
     return(app.FindInternal(QueryExFactory.BlankQuery().Marked(marked), within, timeOut: timeout));
 }
Ejemplo n.º 12
0
 /// <summary>
 /// Attempts to find an element matching the <see cref="to"/> query, scrolling down on
 /// the element matching the <see cref="within"/> query if necessary
 /// </summary>
 /// <param name="app">The application</param>
 /// <param name="to">The query that indicates the element that is searched for within <see cref="within"/></param>
 /// <param name="within">The query that indicates the element where any scrolling required to reach the element will occur</param>
 /// <param name="timeout">[Optionnal] An explicit value for the timeout. If not specified, the default timeout  will be used.</param>
 /// <returns>A query pointing to the resulting element if it was found</returns>
 public static QueryEx FindWithin(this IApp app, QueryEx to, QueryEx within, TimeSpan?timeout = null)
 {
     return(app.FindInternal(to, within, timeOut: timeout));
 }
Ejemplo n.º 13
0
        // Uno specific

        private void TapAt(QueryEx query, double x, double y)
        {
            var firstResult = query.FirstResult();

            _app.TapCoordinates((float)(firstResult.Rect.X + x), (float)(firstResult.Rect.Y + y));
        }
Ejemplo n.º 14
0
        private void ToggleTreeViewItemCheckBox(QueryEx item, int level)
        {
            var firstItem = item.FirstResult();

            _app.TapCoordinates((float)(firstItem.Rect.X + firstItem.Rect.Width * 0.05 * level), (float)(firstItem.Rect.Y + firstItem.Rect.Height * .5));
        }
Ejemplo n.º 15
0
 private string GetText(QueryEx textBlock) => textBlock.GetDependencyPropertyValue <string>("Text");
Ejemplo n.º 16
0
        internal static QueryEx FindInternal(this IApp app, QueryEx target, QueryEx within = null, FindScrollDirection direction = FindScrollDirection.DownThenUp, TimeSpan?timeOut = null)
        {
            // TODO: Add Visibility check here ?

            if (AttemptToFindTargetBeforeScrolling && target.HasResults())
            {
                return(target);
            }

            Action executeScrollDownTo;
            Action executeScrollUpTo;

            if (within == null)
            {
                executeScrollDownTo = () =>
                {
                    app.ScrollDownTo(
                        toQuery: target,
                        strategy: DefaultScrollStrategy,
                        swipeSpeed: InstantSwipeSpeed,
                        withInertia: false,
                        timeout: timeOut
                        );
                };

                executeScrollUpTo = () =>
                {
                    app.ScrollUpTo(
                        toQuery: target,
                        strategy: DefaultScrollStrategy,
                        swipeSpeed: InstantSwipeSpeed,
                        withInertia: false,
                        timeout: timeOut
                        );
                };
            }
            else
            {
                executeScrollDownTo = () =>
                {
                    app.ScrollDownTo(
                        toQuery: target,
                        withinQuery: within,
                        strategy: DefaultScrollStrategy,
                        swipeSpeed: InstantSwipeSpeed,
                        withInertia: false,
                        timeout: timeOut
                        );
                };

                executeScrollUpTo = () =>
                {
                    app.ScrollUpTo(
                        toQuery: target,
                        withinQuery: within,
                        strategy: DefaultScrollStrategy,
                        swipeSpeed: InstantSwipeSpeed,
                        withInertia: false,
                        timeout: timeOut
                        );
                };
            }

            // First step. Ignore misses if search is two-step process
            switch (direction)
            {
            case FindScrollDirection.Down:
                executeScrollDownTo();
                return(target);

            case FindScrollDirection.DownThenUp:
                try
                {
                    executeScrollDownTo();
                }
                catch (Exception) { }
                break;

            case FindScrollDirection.Up:
                executeScrollUpTo();
                return(target);

            case FindScrollDirection.UpThenDown:
                try
                {
                    executeScrollUpTo();
                }
                catch (Exception) { }
                break;
            }

            // Second step (if the search is a two step process)
            switch (direction)
            {
            case FindScrollDirection.DownThenUp:
                executeScrollUpTo();
                break;

            case FindScrollDirection.UpThenDown:
                executeScrollDownTo();
                break;
            }

            return(target);
        }
Ejemplo n.º 17
0
    // Async versions of the Uno.UITest.Helpers.Queries.QueryExtensions
    // Those are only mapping to the sync version but are needed to allow
    // multi-targeting with **Runtime UI tests** engine which has only async versions.

    public static async Task WaitForDependencyPropertyValueAsync(
        this IApp app,
        QueryEx element,
        string dependencyPropertyName,
        string value)
    => app.WaitForDependencyPropertyValue(element, dependencyPropertyName, value);
Ejemplo n.º 18
0
 /// <summary>
 /// Set the current scroll context (used in operations such as <see cref="FindWithinContext"/>), and returns
 /// a disposable handle which will restore the previous context when disposed
 /// </summary>
 /// <param name="app">The application</param>
 /// <param name="scrollContext">The scroll context to set</param>
 /// <returns></returns>
 public static IDisposable WithScrollContext(IApp app, QueryEx scrollContext)
 {
     return(new ScrollContextTracker(scrollContext));
 }
Ejemplo n.º 19
0
        // [Timeout(3000000)] // Timeout is now moved to individual platorms runners configuration in CI
        public async Task RunRuntimeTests()
        {
            Run("SamplesApp.Samples.UnitTests.UnitTestsPage");

            IAppQuery AllQuery(IAppQuery query)
            // .All() is not yet supported for wasm.
            => AppInitializer.GetLocalPlatform() == Platform.Browser ? query : query.All();

            var runButton          = new QueryEx(q => AllQuery(q).Marked("runButton"));
            var failedTests        = new QueryEx(q => AllQuery(q).Marked("failedTests"));
            var failedTestsDetails = new QueryEx(q => AllQuery(q).Marked("failedTestDetails"));
            var unitTestsControl   = new QueryEx(q => AllQuery(q).Marked("UnitTestsRootControl"));

            async Task <bool> IsTestExecutionDone()
            {
                return(await GetWithRetry("IsTestExecutionDone", () => unitTestsControl.GetDependencyPropertyValue("RunningStateForUITest")?.ToString().Equals("Finished", StringComparison.OrdinalIgnoreCase) ?? false));
            }

            _app.WaitForElement(runButton);

            if (Environment.GetEnvironmentVariable(TestResultsOutputFilePath) is { } path)
            {
                // Used to disable showing the test output visually
                unitTestsControl.SetDependencyPropertyValue("IsRunningOnCI", "true");

                // Used to perform test grouping on CI to reduce the impact of re-runs
                if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(TestGroupVariable)))
                {
                    unitTestsControl.SetDependencyPropertyValue("CITestGroup", Environment.GetEnvironmentVariable(TestGroupVariable));
                    unitTestsControl.SetDependencyPropertyValue("CITestGroupCount", Environment.GetEnvironmentVariable(TestGroupCountVariable));
                }
            }

            _app.FastTap(runButton);

            var lastChange = DateTimeOffset.Now;
            var lastValue  = "";

            while (DateTimeOffset.Now - lastChange < TestRunTimeout)
            {
                var newValue = await GetWithRetry("GetRunTestCount", () => unitTestsControl.GetDependencyPropertyValue("RunTestCountForUITest")?.ToString());

                if (lastValue != newValue)
                {
                    lastChange = DateTimeOffset.Now;
                }

                await Task.Delay(TimeSpan.FromSeconds(.5));

                if (await IsTestExecutionDone())
                {
                    break;
                }
            }

            if (!await IsTestExecutionDone())
            {
                Assert.Fail("A test run timed out");
            }

            TestContext.AddTestAttachment(await ArchiveResults(unitTestsControl), "runtimetests-results.zip");

            var count = GetValue(nameof(unitTestsControl), unitTestsControl, "FailedTestCountForUITest");

            if (count != "0")
            {
                var tests = GetValue(nameof(failedTests), failedTests)
                            .Split(new char[] { '§' }, StringSplitOptions.RemoveEmptyEntries)
                            .Select((x, i) => $"\t{i + 1}. {x}\n")
                            .ToArray();
                var details = GetValue(nameof(failedTestsDetails), failedTestsDetails);

                Assert.Fail($"{tests.Length} unit test(s) failed (count={count}).\n\tFailing Tests:\n{string.Join("", tests)}\n\n---\n\tDetails:\n{details}");
            }

            TakeScreenshot("Runtime Tests Results", ignoreInSnapshotCompare: true);
        }
Ejemplo n.º 20
0
        private void TranslateOverElement(QueryEx element)
        {
            var rect = _app.WaitForElement(element).Single().Rect;

            _app.DragCoordinates(rect.X + 2, rect.Y + 2, rect.Right - 2, rect.Bottom - 2);
        }