Skip to content

Commit

Permalink
Merge pull request FlaUI#144 from Roemer/RecordTests
Browse files Browse the repository at this point in the history
Recorder improvements
  • Loading branch information
Roemer authored Feb 16, 2018
2 parents 5e6d3fa + e0bcd71 commit 0de6187
Show file tree
Hide file tree
Showing 14 changed files with 327 additions and 190 deletions.
4 changes: 2 additions & 2 deletions src/FlaUI.Core.UITests/CaptureTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using FlaUI.Core.Capturing;
using FlaUI.Core.Logging;
using FlaUI.Core.Tools;
using FlaUI.Core.UITests.TestTools;
using FlaUI.Core.UITests.TestFramework;
using FlaUI.UIA3;
using NUnit.Framework;

Expand Down Expand Up @@ -37,7 +37,7 @@ public void VideoTest()
{
Logger.Default = new NUnitProgressLogger();
Logger.Default.SetLevel(LogLevel.Debug);
SystemInfo.Refresh();
SystemInfo.RefreshAll();
var recordingStartTime = DateTime.UtcNow;
var recorder = new VideoRecorder(10, 26, @"C:\Users\rbl\Documents\ffmpeg.exe", @"C:\temp\out.mp4", () =>
{
Expand Down
2 changes: 1 addition & 1 deletion src/FlaUI.Core.UITests/FlaUI.Core.UITests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
<Compile Include="TestFramework\TestApplicationType.cs" />
<Compile Include="TestFramework\TestUtilities.cs" />
<Compile Include="TestFramework\UITestBase.cs" />
<Compile Include="TestTools\NUnitProgressLogger.cs" />
<Compile Include="TestFramework\NUnitProgressLogger.cs" />
<Compile Include="XPathTests.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using FlaUI.Core.Logging;
using NUnit.Framework;

namespace FlaUI.Core.UITests.TestTools
namespace FlaUI.Core.UITests.TestFramework
{
public class NUnitProgressLogger : LoggerBase
{
Expand Down
110 changes: 80 additions & 30 deletions src/FlaUI.Core.UITests/TestFramework/UITestBase.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using System;
using System.IO;
using System.Threading.Tasks;
using FlaUI.Core.Capturing;
using FlaUI.Core.Logging;
using FlaUI.Core.UITests.TestTools;
using FlaUI.Core.Tools;
using NUnit.Framework;
using NUnit.Framework.Interfaces;

Expand All @@ -14,18 +15,26 @@ namespace FlaUI.Core.UITests.TestFramework
public abstract class UITestBase
{
/// <summary>
/// Flag which indicates if any test was run on a new instance of the app
/// Flag which indicates if any test was run on a new instance of the app.
/// </summary>
private bool _wasTestRun;

/// <summary>
/// Flag which indicates if the test fixture has at least one failing test.
/// </summary>
private bool _hasFailedTest;

private VideoRecorder _recorder;
private string _testMethodName;

protected AutomationType AutomationType { get; }

protected TestApplicationType ApplicationType { get; }

/// <summary>
/// Path of the directory for the screenshots
/// Path of the directory for the screenshots and videos for failed tests.
/// </summary>
protected string ScreenshotDir { get; }
protected string FailedTestsData { get; }

/// <summary>
/// Instance of the current running application
Expand All @@ -38,7 +47,7 @@ protected UITestBase(AutomationType automationType, TestApplicationType appType)
{
AutomationType = automationType;
ApplicationType = appType;
ScreenshotDir = @"c:\FailedTestsScreenshots";
FailedTestsData = @"c:\FailedTestsData";
_wasTestRun = false;
Automation = TestUtilities.GetAutomation(automationType);
Logger.Default = new NUnitProgressLogger();
Expand All @@ -48,35 +57,49 @@ protected UITestBase(AutomationType automationType, TestApplicationType appType)
/// Setup which starts the application (once per test-class)
/// </summary>
[OneTimeSetUp]
public void BaseSetup()
public async Task BaseSetup()
{
switch (ApplicationType)
// Start the recorder
SystemInfo.RefreshAll();
var ffmpegPath = await VideoRecorder.DownloadFFMpeg(@"C:\temp");
var recordingStartTime = DateTime.UtcNow;
_recorder = new VideoRecorder(15, 26, ffmpegPath, $@"C:\temp\{TestContext.CurrentContext.Test.ClassName}.mp4", () =>
{
case TestApplicationType.Custom:
App = StartApplication();
break;
case TestApplicationType.WinForms:
App = Application.Launch(Path.Combine(TestContext.CurrentContext.TestDirectory, @"..\..\TestApplications\WinFormsApplication\bin\WinFormsApplication.exe"));
break;
case TestApplicationType.Wpf:
App = Application.Launch(Path.Combine(TestContext.CurrentContext.TestDirectory, @"..\..\TestApplications\WpfApplication\bin\WpfApplication.exe"));
break;
default:
throw new ArgumentOutOfRangeException();
}
App.WaitWhileMainHandleIsMissing();
var testName = TestContext.CurrentContext.Test.ClassName + "." + (_testMethodName ?? "[Setup]");
var img = Capture.Screen();
img.ApplyOverlays(new InfoOverlay(img.DesktopBounds) { CustomTimeSpan = DateTime.UtcNow - recordingStartTime, OverlayStringFormat = @"{ct:hh\:mm\:ss\.fff} / {name} / CPU: {cpu} / RAM: {mem.p.used}/{mem.p.tot} ({mem.p.used.perc}) / " + testName }, new MouseOverlay(img.DesktopBounds));
return img;
});
await Task.Delay(500);
StartTestApplication();
}

/// <summary>
/// Closes the application after all tests were run
/// Closes the application after all tests were run.
/// </summary>
[OneTimeTearDown]
public void BaseTeardown()
public async Task BaseTeardown()
{
Automation.Dispose();
App.Close();
App.Dispose();
App = null;
StopTestApplication();
await Task.Delay(500);
_recorder.Stop();
if (_hasFailedTest)
{
Directory.CreateDirectory(FailedTestsData);
File.Move(_recorder.TargetVideoPath, Path.Combine(FailedTestsData, Path.GetFileName(_recorder.TargetVideoPath)));
}
else
{
File.Delete(_recorder.TargetVideoPath);
}
_recorder.Dispose();
}

[SetUp]
public void BaseTestSetup()
{
_testMethodName = TestContext.CurrentContext.Test.MethodName;
}

/// <summary>
Expand All @@ -90,6 +113,7 @@ public void BaseTestTeardown()
// Make a screenshot if the test failed
if (TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Failed)
{
_hasFailedTest = true;
TakeScreenshot(TestContext.CurrentContext.Test.FullName);
}
}
Expand All @@ -110,24 +134,50 @@ protected void RestartApp()
// Don't restart if no test was already run on it
if (!_wasTestRun) return;
// Restart the application
BaseTeardown();
BaseSetup();
StopTestApplication();
StartTestApplication();
_wasTestRun = false;
}

private void StartTestApplication()
{
switch (ApplicationType)
{
case TestApplicationType.Custom:
App = StartApplication();
break;
case TestApplicationType.WinForms:
App = Application.Launch(Path.Combine(TestContext.CurrentContext.TestDirectory, @"..\..\TestApplications\WinFormsApplication\bin\WinFormsApplication.exe"));
break;
case TestApplicationType.Wpf:
App = Application.Launch(Path.Combine(TestContext.CurrentContext.TestDirectory, @"..\..\TestApplications\WpfApplication\bin\WpfApplication.exe"));
break;
default:
throw new ArgumentOutOfRangeException();
}
App.WaitWhileMainHandleIsMissing();
}

private void StopTestApplication()
{
App.Close();
App.Dispose();
App = null;
}

private void TakeScreenshot(string screenshotName)
{
var imagename = screenshotName + ".png";
imagename = imagename.Replace("\"", String.Empty);
var imagePath = Path.Combine(ScreenshotDir, imagename);
var imagePath = Path.Combine(FailedTestsData, imagename);
try
{
Directory.CreateDirectory(ScreenshotDir);
Directory.CreateDirectory(FailedTestsData);
Capture.Screen().ToFile(imagePath);
}
catch (Exception ex)
{
Console.WriteLine("Failed to save screenshot to directory: {0}, filename: {1}, Ex: {2}", ScreenshotDir, imagePath, ex);
Console.WriteLine("Failed to save screenshot to directory: {0}, filename: {1}, Ex: {2}", FailedTestsData, imagePath, ex);
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/FlaUI.Core/AutomationElementXPathNavigator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,10 @@ private string GetAttributeName(int attributeIndex)

private int GetAttributeIndexFromName(string attributeName)
{
ElementAttributes parsedValue;
#if NET35
if (ExtensionMethods.TryParse(attributeName, out parsedValue))
if (EnumExtensions.TryParse(attributeName, out ElementAttributes parsedValue))
#else
if (Enum.TryParse(attributeName, out parsedValue))
if (Enum.TryParse(attributeName, out ElementAttributes parsedValue))
#endif
{
return (int)parsedValue;
Expand Down
2 changes: 1 addition & 1 deletion src/FlaUI.Core/Capturing/Capture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public static CaptureImage Rectangle(Rectangle bounds)
var hDest = Gdi32.CreateCompatibleDC(hSrce);
var hBmp = Gdi32.CreateCompatibleBitmap(hSrce, sz.Width, sz.Height);
var hOldBmp = Gdi32.SelectObject(hDest, hBmp);
Gdi32.BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, (int)bounds.X, (int)bounds.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
Gdi32.BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, bounds.X, bounds.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
var bmp = Image.FromHbitmap(hBmp);
Gdi32.SelectObject(hDest, hOldBmp);
Gdi32.DeleteObject(hBmp);
Expand Down
2 changes: 1 addition & 1 deletion src/FlaUI.Core/Capturing/InfoOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public override void Draw(Graphics g)

private string FormatOverlayString(string overlayString)
{
SystemInfo.Refresh();
SystemInfo.RefreshAll();
// Replace the simple values
overlayString = overlayString
.Replace("{name}", $"{Environment.MachineName}")
Expand Down
Loading

0 comments on commit 0de6187

Please sign in to comment.