Skip to content

Commit

Permalink
perf(tests): Improved perf of UI tests by reducing multiple decoding …
Browse files Browse the repository at this point in the history
…of same images
  • Loading branch information
carldebilly committed Nov 11, 2020
1 parent 0c33868 commit c0c391b
Show file tree
Hide file tree
Showing 38 changed files with 269 additions and 285 deletions.
2 changes: 1 addition & 1 deletion src/SamplesApp/SamplesApp.Droid/SamplesApp.Droid.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode>
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
<EmbedAssembliesIntoApk>false</EmbedAssembliesIntoApk>
<AotAssemblies>false</AotAssemblies>
<EnableLLVM>false</EnableLLVM>
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
Expand Down
5 changes: 4 additions & 1 deletion src/SamplesApp/SamplesApp.Shared/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,10 @@ public static string GetAllTests()
=> SampleControl.Presentation.SampleChooserViewModel.Instance.GetAllSamplesNames();

public static string GetDisplayScreenScaling(string displayId)
=> (DisplayInformation.GetForCurrentView().LogicalDpi * 100f / 96f).ToString(CultureInfo.InvariantCulture);
{
var screenScaling = Android.App.Application.Context.Resources.DisplayMetrics.Density * 100f;
return screenScaling.ToString(CultureInfo.InvariantCulture);
}

public static string RunTest(string metadataName)
{
Expand Down
2 changes: 1 addition & 1 deletion src/SamplesApp/SamplesApp.UITests/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public class Constants
public const string iOSDeviceNameOrId = "iPad Pro (12.9-inch) (4th generation)";

// Default active platform when running under Visual Studio test runner
public const Platform CurrentPlatform = Platform.Browser;
public const Platform CurrentPlatform = Platform.Android;
}
}
19 changes: 2 additions & 17 deletions src/SamplesApp/SamplesApp.UITests/SampleControlUITestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,24 +317,9 @@ public IAppRect ToPhysicalRect(IAppRect logicalRect)

internal float GetDisplayScreenScaling() => _app.GetDisplayScreenScaling();

/// <summary>
/// Get the center of <paramref name="rect"/> adjusted for the display scale, appropriate for screenshot analysis.
/// </summary>
protected PointF GetScaledCenter(IAppRect rect)
{
var scale = (float)GetDisplayScreenScaling();
return new PointF(rect.CenterX * scale, rect.CenterY * scale);
}
internal float LogicalToPhysical(float logical) => logical * GetDisplayScreenScaling();

/// <summary>
/// Get centre of the bounds rect of element <paramref name="elementName"/> adjusted for the display scale, appropriate for
/// screenshot analysis.
/// </summary>
protected PointF GetRectCenterScaled(string elementName)
{
var rect = _app.GetRect(elementName);
return GetScaledCenter(rect);
}
internal float PhysicalToLogical(float physical) => physical / GetDisplayScreenScaling();

protected bool GetIsCurrentRotationLandscape(string elementName)
{
Expand Down
20 changes: 18 additions & 2 deletions src/SamplesApp/SamplesApp.UITests/ScreenshotInfo.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
using System.IO;
#nullable enable
using System;
using System.Drawing;
using System.IO;

namespace SamplesApp.UITests
{
public class ScreenshotInfo
public class ScreenshotInfo : IDisposable
{
private Bitmap? _bitmap;
public FileInfo File { get; }

public string StepName { get; }
Expand All @@ -17,5 +21,17 @@ public ScreenshotInfo(FileInfo file, string stepName)
public static implicit operator FileInfo(ScreenshotInfo si) => si.File;

public static implicit operator ScreenshotInfo(FileInfo fi) => new ScreenshotInfo(fi, fi.Name);

public Bitmap GetBitmap() => _bitmap ??= new Bitmap(File.FullName);
public void Dispose()
{
_bitmap?.Dispose();
_bitmap = null;
}

~ScreenshotInfo()
{
Dispose();
}
}
}
79 changes: 34 additions & 45 deletions src/SamplesApp/SamplesApp.UITests/TestFramework/ImageAssert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public static void AreAlmostEqual(ScreenshotInfo expected, Rectangle expectedRec
PixelTolerance tolerance,
[CallerLineNumber] int line = 0)
{
using var actualBitmap = new Bitmap(actual.File.FullName);
var actualBitmap = actual.GetBitmap();
AreEqualImpl(expected, expectedRect, actual, actualBitmap, actualRect, expectedToActualScale, tolerance, line);
}

Expand Down Expand Up @@ -122,7 +122,7 @@ public static void AreAlmostEqual(ScreenshotInfo expected, Rectangle expectedRec
PixelTolerance tolerance,
[CallerLineNumber] int line = 0)
{
using var expectedBitmap = new Bitmap(expected.File.FullName);
var expectedBitmap = expected.GetBitmap();

if (expectedRect != FirstQuadrant && actualRect != FirstQuadrant)
{
Expand Down Expand Up @@ -188,7 +188,7 @@ public static void AreNotEqual(ScreenshotInfo expected, Rectangle expectedRect,
PixelTolerance tolerance,
int line)
{
using var actualBitmap = new Bitmap(actual.File.FullName);
var actualBitmap = actual.GetBitmap();
AreNotEqualImpl(expected, expectedRect, actual, actualBitmap, actualRect, expectedToActualScale, tolerance, line);
}

Expand Down Expand Up @@ -224,39 +224,31 @@ public static void HasColorAt(ScreenshotInfo screenshot, float x, float y, Color

private static void HasColorAtImpl(ScreenshotInfo screenshot, int x, int y, Color expectedColor, byte tolerance, int line)
{
var file = screenshot?.File;
if (file == null)
{
Assert.Fail("No file");
return;
}
var bitmap = screenshot.GetBitmap();

using (var bitmap = new Bitmap(file.FullName))
if (bitmap.Width <= x || bitmap.Height <= y)
{
if (bitmap.Width <= x || bitmap.Height <= y)
{
Assert.Fail(WithContext($"Coordinates ({x}, {y}) falls outside of screenshot dimension {bitmap.Size}"));
}
Assert.Fail(WithContext($"Coordinates ({x}, {y}) falls outside of screenshot dimension {bitmap.Size}"));
}

var pixel = bitmap.GetPixel(x, y);
var pixel = bitmap.GetPixel(x, y);

if (!AreSameColor(expectedColor, pixel, tolerance, out var difference))
{
Assert.Fail(WithContext(builder: builder => builder
.AppendLine($"Color at ({x},{y}) is not expected")
.AppendLine($"expected: {ToArgbCode(expectedColor)} {expectedColor}")
.AppendLine($"actual : {ToArgbCode(pixel)} {pixel}")
.AppendLine($"tolerance: {tolerance}")
.AppendLine($"difference: {difference}")
));
}
if (!AreSameColor(expectedColor, pixel, tolerance, out var difference))
{
Assert.Fail(WithContext(builder: builder => builder
.AppendLine($"Color at ({x},{y}) is not expected")
.AppendLine($"expected: {ToArgbCode(expectedColor)} {expectedColor}")
.AppendLine($"actual : {ToArgbCode(pixel)} {pixel}")
.AppendLine($"tolerance: {tolerance}")
.AppendLine($"difference: {difference}")
));
}

string WithContext(string message = null, Action<StringBuilder> builder = null)
{
return new StringBuilder()
.AppendLine($"ImageAssert.HasColorAt @ line {line}")
.AppendLine($"screenshot: {screenshot.StepName} ({file.Name})")
.AppendLine($"screenshot: {screenshot.StepName} ({screenshot.File.Name})")
.AppendLine("====================")
.ApplyIf(message != null, sb => sb.AppendLine(message))
.ApplyIf(builder != null, builder)
Expand All @@ -274,32 +266,29 @@ public static void DoesNotHaveColorAt(ScreenshotInfo screenshot, float x, float

private static void DoesNotHaveColorAtImpl(ScreenshotInfo screenshot, int x, int y, Color excludedColor, byte tolerance, int line)
{
var file = screenshot.File;
using (var bitmap = new Bitmap(file.FullName))
var bitmap = screenshot.GetBitmap();
if (bitmap.Width <= x || bitmap.Height <= y)
{
if (bitmap.Width <= x || bitmap.Height <= y)
{
Assert.Fail(WithContext($"Coordinates ({x}, {y}) falls outside of screenshot dimension {bitmap.Size}"));
}
Assert.Fail(WithContext($"Coordinates ({x}, {y}) falls outside of screenshot dimension {bitmap.Size}"));
}

var pixel = bitmap.GetPixel(x, y);
if (AreSameColor(excludedColor, pixel, tolerance, out var difference))
{
Assert.Fail(WithContext(builder: builder => builder
.AppendLine($"Color at ({x},{y}) is not expected")
.AppendLine($"excluded: {ToArgbCode(excludedColor)} {excludedColor.Name}")
.AppendLine($"actual : {ToArgbCode(pixel)} {pixel}")
.AppendLine($"tolerance: {tolerance}")
.AppendLine($"difference: {difference}")
));
}
var pixel = bitmap.GetPixel(x, y);
if (AreSameColor(excludedColor, pixel, tolerance, out var difference))
{
Assert.Fail(WithContext(builder: builder => builder
.AppendLine($"Color at ({x},{y}) is not expected")
.AppendLine($"excluded: {ToArgbCode(excludedColor)} {excludedColor.Name}")
.AppendLine($"actual : {ToArgbCode(pixel)} {pixel}")
.AppendLine($"tolerance: {tolerance}")
.AppendLine($"difference: {difference}")
));
}

string WithContext(string message = null, Action<StringBuilder> builder = null)
{
return new StringBuilder()
.AppendLine($"ImageAssert.DoesNotHaveColorAt @ line {line}")
.AppendLine($"screenshot: {screenshot.StepName} ({file.Name})")
.AppendLine($"screenshot: {screenshot.StepName} ({screenshot.File.Name})")
.AppendLine("====================")
.ApplyIf(message != null, sb => sb.AppendLine(message))
.ApplyIf(builder != null, builder)
Expand All @@ -311,7 +300,7 @@ string WithContext(string message = null, Action<StringBuilder> builder = null)
#region HasPixels
public static void HasPixels(ScreenshotInfo actual, params ExpectedPixels[] expectations)
{
using var bitmap = new Bitmap(actual.File.FullName);
var bitmap = actual.GetBitmap();
using var assertionScope = new AssertionScope("ImageAssert");

foreach (var expectation in expectations)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ public void ElevatedView_Corners_Validation()

_app.WaitForElement("Elevation");

var elevationRect = _app.GetRect("Elevation");
var elevationRect = _app.GetPhysicalRect("Elevation");

var snapshot = this.TakeScreenshot("check", ignoreInSnapshotCompare: true);
using var snapshot = this.TakeScreenshot("check", ignoreInSnapshotCompare: true);

const string white = "#FFFFFF";
const string gray = "#A9A9A9"; // DarkGray
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using NUnit.Framework;
using Uno.UITest.Helpers;
using Uno.UITest.Helpers.Queries;
Expand All @@ -18,7 +19,6 @@ partial class UnoSamples_Tests : SampleControlUITestBase

[Test]
[AutoRetry]
[ActivePlatforms(Platform.iOS)] // Android is disabled https://github.com/unoplatform/uno/issues/1635
public void Elevation_Validation()
{
Run("UITests.Shared.Toolkit.Elevation");
Expand All @@ -28,15 +28,15 @@ public void Elevation_Validation()
var turnElevation_ON_Button = _app.Marked("TurnElevation_ON_Button");

// Take ScreenShot with no elevation
var screenshot_NoElevation = TakeScreenshot("Elevation - No Elevation");
using var screenshot_NoElevation = TakeScreenshot("Elevation - No Elevation");

turnElevation_ON_Button.FastTap();
turnElevation_ON_Button.Tap();

// Take ScreenShot of with elevation
var screenshot_WithElevation = TakeScreenshot("Elevation - With Elevation");
using var screenshot_WithElevation = TakeScreenshot("Elevation - With Elevation");

Bitmap img1 = new Bitmap(screenshot_NoElevation.ToString());
Bitmap img2 = new Bitmap(screenshot_WithElevation.ToString());
var img1 = screenshot_NoElevation.GetBitmap();
var img2 = screenshot_WithElevation.GetBitmap();

float diffPercentage = 0;
float diff = 0;
Expand All @@ -61,10 +61,8 @@ public void Elevation_Validation()
}

diffPercentage = 100 * (diff / 255) / (img1.Width * img1.Height * 3);
if (diffPercentage < 0.5)
{
Assert.Fail("Images are the same");
}

diffPercentage.Should().BeGreaterThan(0.01f, "Before/After are too similar");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ public void Keyboard_DismissTesting()

_app.WaitForElement(singleTextBox);

var initial = TakeScreenshot("initial", ignoreInSnapshotCompare: true);
using var initial = TakeScreenshot("initial", ignoreInSnapshotCompare: true);

singleTextBox.FastTap();
_app.Wait(2);
Expand All @@ -444,7 +444,7 @@ public void Keyboard_DismissTesting()
_app.Wait(3);
_app.Back();

var final = TakeScreenshot("final", ignoreInSnapshotCompare: true);
using var final = TakeScreenshot("final", ignoreInSnapshotCompare: true);

// We only validate that the bottom of the screen is the same (so the keyboard is no longer visible).
// This is to avoid content offset if the status bar was opened by the keyboard or the message box.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void When_Clip_Is_Set_On_Container_Element()
var rect1 = grid1.FirstResult().Rect;
var rect2 = grid2.FirstResult().Rect;

var screenshot = TakeScreenshot("Clipping");
using var screenshot = TakeScreenshot("Clipping");

ImageAssert.HasColorAt(screenshot, rect1.Right + 8, rect1.Y + 75, Color.Blue);
ImageAssert.HasColorAt(screenshot, rect1.X + 75, rect1.Bottom + 8, Color.Blue);
Expand All @@ -42,16 +42,14 @@ public void When_Clipped_Rounded_Corners()

_app.WaitForElement("RoundedGrid");

var rect = _app.GetRect("RoundedGrid");
var rect = _app.GetPhysicalRect("RoundedGrid");

var centre = GetScaledCenter(rect);
var scale = GetDisplayScreenScaling();
var offset = 5 * (float)scale;
var offset = LogicalToPhysical(5);
var innerCornerX = rect.X + offset;
var innerCornerY = rect.Y + offset;

var screenshot = TakeScreenshot("ClippedCorners");
ImageAssert.HasColorAt(screenshot, centre.X, centre.Y, Color.Blue);
using var screenshot = TakeScreenshot("ClippedCorners");
ImageAssert.HasColorAt(screenshot, rect.X, rect.Y, Color.Blue);
ImageAssert.HasColorAt(screenshot, innerCornerX, innerCornerY, Color.Red);

}
Expand All @@ -64,7 +62,7 @@ public void When_CornerRadiusControls()

_app.WaitForElement("TestRoot");

var snapshot = this.TakeScreenshot("validation", ignoreInSnapshotCompare: false);
using var snapshot = this.TakeScreenshot("validation", ignoreInSnapshotCompare: false);

using (new AssertionScope("Rounded corners"))
{
Expand All @@ -86,7 +84,7 @@ public void When_CornerRadiusControls()

void CheckRoundedCorners(string s)
{
var rectCtl = _app.GetRect(s);
var rectCtl = _app.GetPhysicalRect(s);

var green = "#FF008000";
var white = "#FFFFFFFF";
Expand Down Expand Up @@ -126,7 +124,7 @@ void CheckRoundedCorners(string s)

void CheckNoRoundedCorners(string s)
{
var rectCtl = _app.GetRect(s);
var rectCtl = _app.GetPhysicalRect(s);

var green = "#FF008000";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void When_Native_View()
_app.WaitForElement("SpacerBorder");
var spacerRect = _app.GetRect("SpacerBorder");

var scrn = TakeScreenshot("Ready");
using var scrn = TakeScreenshot("Ready");

ImageAssert.HasColorAt(scrn, spacerRect.X, spacerRect.Y, Color.Red);
}
Expand Down
Loading

0 comments on commit c0c391b

Please sign in to comment.