How do I test my c#-based cmdlet? - c#

I've been looking all over the place for a decent example and most results are basics of power shell....
But anyway, I did manage to find this: http://blogs.msdn.com/b/heaths/archive/2008/04/06/functional-testing-of-cmdlets.aspx
Which gave me a start, and allowed me to end up with this test, based of the example in the above link:
using System;
using System.Collections.ObjectModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using MyProject;
namespace Commands.Tests
{
[TestClass]
public class StartServiceTest
{
private RunspaceConfiguration config;
[TestInitialize]
public void Initialize()
{
config = RunspaceConfiguration.Create();
config.Cmdlets.Append(new CmdletConfigurationEntry(
"Start-UseService",
typeof(StartUseServiceCommand),
"Microsoft.Windows.Installer.PowerShell.dll-Help.xml"));
}
[TestMethod]
[DeploymentItem(#"data\example.txt")]
public void PathTest()
{
using (Runspace rs = RunspaceFactory.CreateRunspace(config))
{
rs.Open();
using (Pipeline p = rs.CreatePipeline(#"start-useservice -service ACE"))
{
Collection<PSObject> objs = p.Invoke();
Assert.AreEqual<int>(1, objs.Count);
}
}
}
}
}
The article doesn't explain anything, so I'm sure "data\example.txt" doesn't apply to me, but example.txt is used as a parameter in the example's test. But the method attribute just isn't discussed.
Has anyone successfully wrote a test for their cmdlet?
I'm also looking for a bit of an explanation of what each piece does.
(I'm not new to MSTest, but I've never used the System.Management.Automation/Runspaces Namespace(s) before)
My cmdlet name is Start-UseService

Related

Trying to use Application.Current in TestCase, however Application cannot be imported from System.Windows

I try to unit-test a Gui application code that uses
Application.Current.Dispatcher.Invoke() and would like to use the solution provided by #informatorius in the similar thread Using the WPF Dispatcher in unit tests. The code is listed below.
The problem I have is that Application is not resolved, even if I add using System.Windows. Is there some special mechanism to resolve
Application from within a class library that defines the testcases ?
I have the MSTest.TestFramework and MSTest.TestAdapter packages installed.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class ApplicationInitializer
{
[AssemblyInitialize]
public static void AssemblyInitialize(TestContext context)
{
var waitForApplicationRun = new TaskCompletionSource<bool>();
Task.Run(() =>
{
var application = new Application();
application.Startup += (s, e) => { waitForApplicationRun.SetResult(true); };
application.Run();
});
waitForApplicationRun.Task.Wait();
}
[AssemblyCleanup]
public static void AssemblyCleanup()
{
Application.Current.Dispatcher.Invoke(Application.Current.Shutdown);
}
}
[TestClass]
public class MyTestClass
{
[TestMethod]
public void MyTestMethod()
{
// implementation can access Application.Current.Dispatcher
}
}
Answer pointed me into the right direction:
using System.Windows is not enough, I also needed to add reference to PresentationFramework to the project. Dont really understand the auto magic behind that.

Unit tests missing output in VS2017

EDIT:
I might have found a possible lead.
Checking my Test Runs it would seem as if I have 0 completed runs (even though all my 15 tests complete). Any clues?
I've got a technical interview coming up where testing will be the main focus. I've got rather limited exposure to testing in Visual Studio and can't seem to figure out why my version (VS2017) won't display the output button when I run tests.
Since my limited exposure I've been following along a few PluralSight courses on the subject and have found a decent one covering both LINQ and VS's own unit testing framework.
This is where it should be on VS2015 (I think?):
And this is how it looks for me:
As you can see I'm missing the output button for some god forsaken reason. I've looked in multiple windows (output's debug and tests), but simply cannot see the output.
My unit test follows the instructor's structure with some small changes (like how I set up my TestContext, which follows the structure of this answer to a similar question..
This is my unit test:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ACM.Library.Test
{
[TestClass]
public class BuilderTest
{
private TestContext _testContextInstance;
public TestContext TestContext
{
get { return _testContextInstance; }
set { _testContextInstance = value; }
}
public Builder listBuilder { get; set; }
[TestInitialize]
public void TestInitialize ()
{
this.listBuilder = new Builder();
}
[TestMethod]
public void TestBuildIntegerSequence()
{
var result = listBuilder.BuildIntegerSequence();
foreach(var item in result)
{
TestContext.WriteLine(item.ToString());
}
Assert.IsNotNull(result);
}
}
}
EDIT:
Here is the function I'm testing...
public IEnumerable<int> BuildIntegerSequence()
{
var integers = Enumerable.Range(0, 10);
return integers;
}

ChromeDriver and IEDriver not found in Directory

I have coded a simple test in visual studio using selenium which works in Firefox. However, I'm trying to run the same test on multiple browsers but I keep getting the same error that the drivers are not found in the directory or the PATH environment variable.
I have them downloaded and they are in the project I am working on. I've been trying all the different ways that I have found but nothing is working.
Can anyone help with this? Thanks :)
Here's a snippet of the code:
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Support.UI;
namespace SeleniumTest2
{
//1 test multiple browsers
[TestFixture(typeof(ChromeDriver))]
[TestFixture(typeof(FirefoxDriver))]
[TestFixture(typeof(InternetExplorerDriver))]
public class ClickTestMetaLearning3TestUser<TWebDriver> where TWebDriver : IWebDriver, new()
{
private IWebDriver driver;
private StringBuilder verificationErrors;
private string baseURL;
private bool acceptNextAlert = true;
[SetUp]
public void SetupTest()
{
this.driver = new TWebDriver();
//Runtime.getRuntime().exec("RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 255");
baseURL = "http://url";
verificationErrors = new StringBuilder();
}
We have had to explicitly tell the ChromeDriver where it is located when constructing it :
_chromeDriver = new ChromeDriver(#"<path to the chromedriver.exe");

The name 'ninja' does not exist in the current context

With the below code I get thee following error:
NinjaSteps.cs(16,13): error CS0103: The name 'ninja' does not exist in the current context
The command line I use to compile is:
csc /target:library /reference:C:\Ruby193\lib\ruby\gems\1.9.1\gems\
cuke4nuke-0.4.0\dotnet\Cuke4Nuke.Framework.dll /reference:C:\Fitnesse\FitNesseRo
ot\jediwhale-fitsharp-a78d820\binary\tools\nunit\framework\nunit.framework.dll /
reference:C:\Users\Rahul\Documents\Visual~1\Projects\ConsoleApplication3\Console
Application3\Ninja.dll NinjaSteps.cs
The code I am trying to compile is from a tutorial on Cucumber automation technology:
NinjaSteps.cs:
http://cuke4ninja.com/sec_ninja_survival_net.html
using System;
using System.Collections.Generic;
using System.Text;
using Cuke4Nuke.Framework;
using NUnit.Framework;
using NinjaSurvivalRate;
namespace ConsoleApplication3
{
class NinjaSteps
{ [Given(#"^the ninja has a ([a-z]*) level black-belt$")]
public void TheNinjaHasABlackBelt(String level)
{ ninja = new Ninja(level);
}
[When(#"^attacked by [a\s]*(.*)$")]
public void AttackedBy(String opponent)
{
actions = ninja.AttackedBy(opponent);
}
[Then("^the ninja should (.*)$")]
public void TheNinjaShould(String action)
{
Assert.IsTrue(actions.Contains(action));
}
}
}
Ninja.cs is below, compiled to Ninja.dll:
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
namespace NinjaSurvivalRate
{
public class Ninja
{
public Ninja(String beltLevel)
{
}
public List<String> AttackedBy(String opponent)
{
if ("Chuck Norris" == opponent)
return new List<string>(
new String[] { "run for his life" });
else
return new List<string>(
new String[] { "engage the opponent" });
}
}
}
Answers and feedback will be appreciated. Going through similar threads, I found that the resolution depended on a case by case basis and their was no consistent root cause, and felt I had to detail exact code details to get an understanding of the cause. You time and help will be greatly appreciated. Thanks.
You haven't defined the variable ninja. You need:
var ninja = new Ninja(level);
Do the same for actions.
EDIT:
Actually both the variables are supposed to be fields/properties in the class itself, if I understand your intentions correctly.
The tutorial is not telling you the whole history. If you go to the source code you will see that there is actually a field ninja declared that is initialized in the method TheNinjaHasABlackBelt (that you already have).

Calling Refresh() on a DirectoryCatalog throws ChangeRejectedException if new DLLs found in directory

I'm experimenting with MEF and created a test program to call "plugins" that implement some given interface, which follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ProbeContract
{
public interface IProbe
{
int DoProbe(string what);
List<string> GetCapabilities();
}
}
I created a sample console program which loads the "plugins" from its own assembly and, if any found, from a diretory in which one puts additional DLLs. The program works OK whether the plugins directory is empty (only the "native" plugins are called) or it has compatible DLLs to start with. BUT... if a new DLL is added between loop iterations, the Refresh() method of DirectoryCatalog throws a ChangeRejectedException, which is explained thusly:
The composition remains unchanged. The
changes were rejected because of the
following error(s): The composition
produced a single composition error.
The root cause is provided below.
Review the CompositionException.Errors
property for more detailed
information.
1) Change in exports prevented by
non-recomposable import
'MEFTest.Program.ProberSet
(ContractName="ProbeContract.IProbe")'
on part 'MEFTest.Program'.
The program is below, follow by the code for the DLL I try to add. What am I doing wrong?
using System;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProbeContract;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace MEFTest
{
class Program
{
[ImportMany]
IEnumerable<IProbe> ProberSet { get; set; }
CompositionContainer exportContainer;
DirectoryCatalog pluginCatalog;
AggregateCatalog catalog;
private void Run()
{
catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
string myExecName = Assembly.GetExecutingAssembly().Location;
string myPath = Path.GetDirectoryName(myExecName);
pluginCatalog = new DirectoryCatalog(myPath + "/Plugins");
catalog.Catalogs.Add(pluginCatalog);
exportContainer = new CompositionContainer(catalog);
CompositionBatch compBatch = new CompositionBatch();
compBatch.AddPart(this);
compBatch.AddPart(catalog);
exportContainer.Compose(compBatch);
for (; ; )
{
Console.Write("Press any key to run all probes: ");
Console.ReadKey(true);
Console.WriteLine();
pluginCatalog.Refresh();
foreach (var Prober in ProberSet)
{
Prober.DoProbe("gizmo");
}
}
}
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
}
}
The plugin. The other two plugins are similar, the only difference being they reside in the same assembly as the main program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using ProbeContract;
namespace OtherProbes
{
[Export(typeof(IProbe))]
public class SpankyNewProber : IProbe
{
public int DoProbe(string what)
{
Console.WriteLine("I'm Spanky and New and I'm probing [{0}]", what);
return 0;
}
public List<string> GetCapabilities()
{
List<string> retVal = new List<string>();
retVal.Add("spanky");
retVal.Add("new");
return retVal;
}
}
}
I'm assuming you are using MEF preview 6 because you are seeing rejection exceptions. The reason you are seeing the change being rejected is because your ProberSet is not recomposable. Try changing your ProberSet import to:
[ImportMany(AllowRecomposition=true)]
IEnumerable<IProbe> ProberSet { get; set; }
Doing so will allow for new IProbe exports to be introduced into the Catalog/Container after this import has already been composed.
The idea here is that once you get a stable composition we reject any changes that could potentially destablize that composition and in your case you stated you want a set of non-recomposable IProbe objects so adding new IProbe's after it was intially set would violate that requirement.

Categories