/***************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
This code is licensed under the Visual Studio SDK license terms.
THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
***************************************************************************/
//*************************************************************************************************
// MyTestAdapter.cs
//
// This file defines the MyTest adapter.
//
// Copyright(c) Microsoft Corporation, 2004
//*************************************************************************************************
namespace Microsoft.VisualStudio.TestTools.Samples
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.TestTools.Common;
using Microsoft.VisualStudio.TestTools.Exceptions;
using Microsoft.VisualStudio.TestTools.Execution;
using Microsoft.VisualStudio.TestTools.TestAdapter;
using Microsoft.VisualStudio.TestTools.TestManagement;
/// <summary>
/// MyTest ITestAdapter implementation.
/// The important methods to implement for your adapter are:
/// - ITestAdapter.Initialize: it's useful to store the run id
/// for the test run that this adapter is being instantiated for
/// so that it can be used later for result reporting.
/// - IBaseAdapter.Run: the method that actually runs the test
/// and reports results.
/// </summary>
internal sealed class MyTestAdapter: ITestAdapter, ILoadTestAdapter
{
#region Constructors
/// <summary>
/// Default constructor.
/// </summary>
public MyTestAdapter()
{ }
#endregion
#region ITestAdapter methods
/// <summary>
/// ITestAdapter method: called to initialize run context for this adapter.
/// </summary>
/// <param name="runContext">The run context to be used for this run</param>
public void Initialize(IRunContext runContext)
{
m_runContext = runContext;
m_runId = Guid.Empty;
if (m_runContext != null && m_runContext.RunConfig != null && m_runContext.RunConfig.TestRun != null)
{
m_runId = m_runContext.RunConfig.TestRun.Id;
}
}
/// <summary>
/// ITestAdapter method: called when a message is sent from the UI or the controller.
/// </summary>
/// <param name="obj">The message object</param>
public void ReceiveMessage(object obj)
{
}
/// <summary>
/// ITestAdapter method: called just before the test run finishes and
/// gives the adapter a chance to do any clean-up.
/// </summary>
/// <param name="runContext">The run context for this run</param>
public void PreTestRunFinished(IRunContext runContext)
{
}
#endregion
#region IBaseAdapter methods
/// <summary>
/// IBaseAdapter method: called to execute a test.
/// </summary>
/// <param name="testElement">The test object to run</param>
/// <param name="testContext">The Test conext for this test invocation</param>
// Suppress DoNotCatchGeneralExceptionTypes.
// We want to catch all exceptions here to report a test failure
// in the case of any exception.
[SuppressMessage("Microsoft.Design", "CA1031")]
public void Run(ITestElement testElement, ITestContext testContext)
{
MyTestAssertHelper.ParameterNotNull(testElement, "testElement");
MyTest test = testElement as MyTest;
MyTestAssertHelper.ParameterNotNull(test, "testElement");
// Create a TestResult for storing the results of this test.
// To build just the MyTest TIP and ITestAdapter, use this line for
// reporting results and comment out the result.ProcessExitCode line
// below.
// TestResult result = new TestResult(new ComputerInfo(Environment.MachineName), m_guidRunId, test);
MyTestResult result = new MyTestResult(new ComputerInfo(Environment.MachineName), m_runId, test);
Stopwatch timer = null;
try
{
// Start the timer for this test.
timer = new Stopwatch();
timer.Start();
// Run the test
ProcessStartInfo psi = new ProcessStartInfo(test.CommandLine);
// Apply window style from my test run config.
MyTestRunConfig myConfig = (MyTestRunConfig)m_runContext.RunConfig.TestRun.RunConfiguration.GetTestTypeSpecificData(MyTest.MyTestType);
if (null != myConfig)
{
psi.WindowStyle = myConfig.WindowStyle;
}
Process p = Process.Start(psi);
p.WaitForExit();
// Record the process exit code.
result.ProcessExitCode2 = p.ExitCode;
// Record the result
ComputeResult(result, p.ExitCode);
}
catch (Exception ex)
{
result.Outcome = TestOutcome.Failed;
result.ErrorMessage = ex.Message;
}
catch
{
result.Outcome = TestOutcome.Failed;
result.ErrorMessage = Microsoft.VisualStudio.TestTools.Samples.Properties.Resources.UnhandledNonClsCompliantException;
}
finally
{
if (timer != null)
{
timer.Stop();
result.Duration = timer.Elapsed;
}
}
testContext.ResultSink.AddResult(result);
}
/// <summary>
/// IBaseAdapter method: called when the test run is complete.
/// </summary>
public void Cleanup()
{
}
/// <summary>
/// IBaseAdapter method: called when the user stops the test run.
/// </summary>
public void StopTestRun()
{
}
/// <summary>
/// IBaseAdapter method: called when the test run is aborted.
/// </summary>
public void AbortTestRun()
{
}
/// <summary>
/// IBaseAdapter method: called when the user pauses the test run.
/// </summary>
public void PauseTestRun()
{
}
/// <summary>
/// IBaseAdapter method: called when the user resumes a paused test run.
/// </summary>
public void ResumeTestRun()
{
}
#endregion
#region ILoadTestAdapter methods
/// <summary>
/// ILoadTestAdapter LoadRun method: called to execute a test within a load test
/// Test types that can safely be run in a load test should implement
/// the ILoadTestAdapter interface (which defines just this method).
/// When running in a load test, many threads may be executing the LoadRun
/// method in parallel, so the test adapter must be thread-safe.
/// The LoadRun method is separate from the Run method in case the adapter
/// needs to include any code to ensure thread safety. If not, as in this
/// case, LoadRun can simply call Run().
/// </summary>
public void LoadRun(ITestElement testElement, ITestContext testContext)
{
Run(testElement, testContext);
}
#endregion
#region Private Methods
private void ComputeResult(TestResult result, int exitCode)
{
string passedCodeStr = Environment.GetEnvironmentVariable(MyTest.PassedCodeVarName);
result.Outcome = (string.IsNullOrEmpty(passedCodeStr) || exitCode == Int32.Parse(passedCodeStr)) ? TestOutcome.Passed : TestOutcome.Failed;
if (result.Outcome != TestOutcome.Passed)
{
result.ErrorMessage = string.Format("Expected process exit code: {0}; actual: {1}.", Int32.Parse(passedCodeStr), exitCode);
}
}
#endregion
#region Private data
// Run context
private IRunContext m_runContext;
private Guid m_runId;
#endregion
}
}