/***************************************************************************
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.
***************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using Microsoft.VisualStudio.TestTools.Common;
using Microsoft.VisualStudio.TestTools.Execution;
using Microsoft.VisualStudio.TestTools.TestAdapter;
namespace Microsoft.VisualStudio.TestTools.Samples
{
/// <summary>
/// The typical scenario of host adapter is loading the "code under test" assembly in some
/// hosting environment orproviding any kind of host services to the code under test.
///
/// A host adapter need to wrap at lease one test adapter who does the actual work of running tests.
/// You can get the adapter of given test by using reflection from ITestElement.Adapter,
/// and case it to ITestAdapter.
///
/// The following samples shows how to write a host adapter. It wraps unit test adapter
/// and MyTestAdapter". It does not really create a hosting environment, but it changes
/// the environment variables which would affect the unit test code and code under test
/// if they depend on environment variables. It also affect MyTest, as MyTestAdapter
/// compares the process exit code with environment variable "PassedCode" (if it exists)
/// to decide whether MyTest test passes or fails.
/// </summary>
class MyHostAdapter : ITestAdapter
{
#region Private Data
private const string m_unitTestAdapterType = "Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestAdapter, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private ITestAdapter m_testAdapter;
private string[] m_supportedAdapterList = new string[] { m_unitTestAdapterType, typeof(MyTestAdapter).AssemblyQualifiedName };
private IRunContext m_runContext;
#endregion
#region ITestAdapter
/// <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>
void ITestAdapter.Initialize(IRunContext runContext)
{
m_runContext = runContext;
// We delay Initialize because we don't know which adapter to use so far
}
/// <summary>
/// ITestAdapter method: called when a message is sent from the UI or the controller.
/// </summary>
/// <param name="obj">The message object</param>
void ITestAdapter.ReceiveMessage(object obj)
{
if (null != m_testAdapter)
{
m_testAdapter.ReceiveMessage(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>
void ITestAdapter.PreTestRunFinished(IRunContext runContext)
{
if (null != m_testAdapter)
{
m_testAdapter.PreTestRunFinished(runContext);
}
}
#endregion
#region IBaseAdapter
/// <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>
void IBaseAdapter.Run(ITestElement testElement, ITestContext testContext)
{
m_testAdapter = GetAdapter(testElement);
if (null != m_testAdapter)
{
m_testAdapter.Initialize(m_runContext);
MyHostRunConfigData config = (MyHostRunConfigData)m_runContext.RunConfig.TestRun.RunConfiguration.HostData[MyHostAdapter.Name];
StringDictionary oldVars = new StringDictionary();
foreach (string name in config.EnvironmentVariables.Keys)
{
oldVars.Add(name, Environment.GetEnvironmentVariable(name));
Environment.SetEnvironmentVariable(name, config.EnvironmentVariables[name]);
}
try
{
m_testAdapter.Run(testElement, testContext);
}
finally
{
foreach (string name in oldVars.Keys)
{
Environment.SetEnvironmentVariable(name, oldVars[name]);
}
}
}
else
{
throw new ArgumentException(string.Format("Adapter type '{0}' is not supported.", testElement.Adapter));
}
}
/// <summary>
/// IBaseAdapter method: called when the test run is complete.
/// </summary>
void IBaseAdapter.Cleanup()
{
if (null != m_testAdapter)
{
m_testAdapter.Cleanup();
}
}
/// <summary>
/// IBaseAdapter method: called when the user stops the test run.
/// </summary>
void IBaseAdapter.StopTestRun()
{
if (null != m_testAdapter)
{
m_testAdapter.StopTestRun();
}
}
/// <summary>
/// IBaseAdapter method: called when the test run is aborted.
/// </summary>
void IBaseAdapter.AbortTestRun()
{
if (null != m_testAdapter)
{
m_testAdapter.AbortTestRun();
}
}
/// <summary>
/// IBaseAdapter method: called when the user pauses the test run.
/// </summary>
void IBaseAdapter.PauseTestRun()
{
if (null != m_testAdapter)
{
m_testAdapter.PauseTestRun();
}
}
/// <summary>
/// IBaseAdapter method: called when the user resumes a paused test run.
/// </summary>
void IBaseAdapter.ResumeTestRun()
{
if (null != m_testAdapter)
{
m_testAdapter.ResumeTestRun();
}
}
#endregion
#region Properties
public const string Name = "My Test";
#endregion
#region Private Methods
private ITestAdapter GetAdapter(ITestElement test)
{
foreach(string adapterType in m_supportedAdapterList)
{
if (test.Adapter.Equals(adapterType))
{
return (ITestAdapter)Activator.CreateInstance(Type.GetType(test.Adapter), new Object[] { });
}
}
return null;
}
#endregion
}
}