I want to be able to add hyperlinks to relevant data in the output for a unit test.
I have the following test:
using NUnit.Framework;
namespace BioFire.PanelSoftware.Service.Tests
{
[TestFixture]
public class SimpleTest
{
[Test]
public void Test1()
{
Console.WriteLine("www.google.com"); //not hyperlink
Console.WriteLine(#"C:\Program Files"); //not hyperlink
throw new Exception("My output window will somehow give me a hyperlink to here.");
}
}
}
According to this question, it isn't possible in C#. But it is clearly working for nUnit somehow:
This is very specific to the terminal you are using and I don't believe anything in C# can achieve clickable text. You can technically use Process.Start() from the System.Diagnostics namespace to trigger the default browser to open the webpage you want, but this isn't a hyperlink and would rather be triggered by your specifications
If you are running from within an IDE, you would have to look into the underlying shell and try to swap it out for a different profile (ex. this should be easy on VS Code but I'm unsure if Visual Studio can support it). If you are running from cmd line, then try using the new Windows Terminal App as it supports this functionality
Related
Just switched to VS2022, created new project and see this:
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
Where is all other stuff? Why is that by default now?
Click the link. It redirects to https://learn.microsoft.com/nl-nl/dotnet/core/tutorials/top-level-templates. It has a paragraph stating:
If you want to use the old templates, see the Use the old program style section.
That section mentions that this is the new default. To circumvent it, create a .NET 5-targeting application, and modify your project file:
- <TargetFramework>net5.0</TargetFramework>
+ <TargetFramework>net6.0</TargetFramework>
A workaround I guess would be to create a custom project template.
If you are using Visual Studio, you can install the Classic Console Template
https://marketplace.visualstudio.com/items?itemName=Doomdied.ClassicConsole1
It add old classic console back, then you can forgot the new one.
You can access the args through a special variable with that name in a top level statement class file:
if (args.Length > 0)
{
foreach (var arg in args)
{
Console.WriteLine($"Argument={arg}");
}
}
else
{
Console.WriteLine("No arguments");
}
Similarly, you just return an int to set the exit code:
string? s = Console.ReadLine();
int returnValue = int.Parse(s ?? "-1");
return returnValue;
See:
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements
As to why, there has been a push to clean up the source files from needless whitespace, masses of curly braces, long lists of imports at the top of each file and the explicit namespace declaration, where most everyone syncs the namespaces with the assembly name and solution folder anyway.
It's been a thorn in the eye of many that simple things in c# need 10s of lines of code where they are a single line in node or python or ruby. It's just not productive. Same for Razor templates and Razor files. You just need an IDE to do she right thing. With these changes it should become much easier to be productive from the GitHub, even if you're not using Visual Studio.
Visual Studio 2022 with .NET 6 uses a new template when creating a C# console app. The new template reduces the amount of boilerplate code necessary to write a simple C# program. I believe this change was meant to benefit beginning programmers and those who are new to C#.
New style:
Statements in Program.cs that appear outside of any function are automatically placed in Main().
Function declarations are moved outside Main() and made static.
A number of using statements are implicitly added for common namespaces like System, System.IO, System.Linq, etc.
Example:
// New style
Console.WriteLine("Code in Main()");
Test();
void Test()
{
Console.WriteLine("Test");
}
is roughly equivalent to:
// Old style
using System;
namespace MyApp
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Code in Main()");
Test();
}
static void Test()
{
Console.WriteLine("Test");
}
}
}
There is nothing stopping you from using the old style. You can copy and paste the old-style code above into Program.cs, and it will run just fine.
There is an option now, to disable top-level statements:
I just tried it and it produces an old-style project. :-)
You also don't loose file-scoped namespaces, they still work.
The "other stuff" is all there; it's just a new convention. It isn't obvious as you might use to get things in C# but this is the new way. And of course, you can use the old style with Main(string args) by selecting Do no use top-level statements checkbox when creating the project in Visual Studio or employ the --use-program-main option on the command line, like this:
dotnet new console --use-program-main
As for the magic of accessing the command line arguments with this new style, see my answer here.
I currently have an nunit project outputting a class library 'RegressionTests.dll' that opens the Selenium WebDriver and runs a few dozen UI tests. I have created a WinForm app with a button 'Run Tests'. When clicking this button, I want to execute a series of n-unit tests from RegressionTests.dll.
I had gotten this to work on my local machine using Process.Start("nunit3-console.exe, nunit-console RegressionTests.dll"), but realized that it would only work on my local if I had installed nunit3-console as a standalone app. After realizing this, I dug more into the n-unit documentation and discovered the n-unit engine. I have tried leveraging the n-unit3 Engine in order to run it internally but have faced issues with implementation of the ITestEventListener in the WinForm project. I've attached the code to my button here:
Form1.cs
private void btnRun_Click(object sender, EventArgs e)
{
TestRunner.Run();
}
Inside TestRunner.cs, we have this code:
[Extension(Description = "Test Reporter Extension", EngineVersion = "3.11")]
public class TestRunner : ITestEventListener
{
public static void Run()
{
ITestEngine engine = TestEngineActivator.CreateInstance();
TestPackage package = new TestPackage("RegressionTests.dll");
ITestEventListener testListener = new TestRunner();
using (ITestRunner runner = engine.GetRunner(package))
{
XmlNode result = runner.Run(testListener, TestFilter.Empty);
}
}
public void OnTestEvent(string report)
{
throw new NotImplementedException();
}
}
Currently, the solution layout is as follows.
Solution
Regression (project)
RegressionTests.dll
TestRunner.cs (file that contains my code linked above)
SeleniumFormApp
Form1.cs (contains button that, upon click, should run Selenium test cases)
How can I leverage n-units Nuget packages to accomplish what I want to here? Is n-unit engine the proper one? If so, how should the ITestEventListener be implemented to accomplish this?
Thank you - please let me know if this is unclear.
I'm trying to execute test program which uses selenium web driver in custom test runner.
In the test runner, selenium web driver equiped test method is invoked by reflection.
When the test program is run by Visual Studio Test Explorer, it works fine.
Problem occurs when it is run dynamically by reflection.
The test program is as follows.
namespace TrialWebUnitTest
{
public class WebDriverTest01
{
private IWebDriver driver;
[TestMethod]
public void NavigateToSeleniumHQByChrome()
{
string TargetUrl = "https://www.seleniumhq.org/projects/webdriver/";
this.driver = new ChromeDriver();
driver.Manage().Window.Size = new System.Drawing.Size(1000, 800); // <- driver throws exception here.
this.driver.Navigate().GoToUrl(TargetUrl);
this.driver.Dispose();
}
}
}
The custom test runner's core test executing method is as follows.
namespace TrialWebUnitTestRunner
{
public partial class TestForm : Form
{
// test button click's event handler.
private void TestButton_Click(object sender, EventArgs e)
{
string retErrorMsg = string.Empty;
if (!ExecTestDynamically(ref retErrorMsg))
{
// show error information in UI textbox.
this.this.ResultMessage.Text = retErrorMsg;
}
}
internal bool ExecTestDynamically(ref string retErrorMsg)
{
var target = new TrialWebUnitTest.WebDriverTest01();
System.Type targetType = typeof(TrialWebUnitTest.WebDriverTest01);
var method = targetType.GetMethod("NavigateToSeleniumHQByChrome");
try
{
method.Invoke(target, null);
return true
}
catch (Exception exp)
{
retErrorMsg = exp.Message + Environment.NewLine + exp.StackTrance;
return false;
}
}
}
}
Exception information
System.InvalidOperationException:
disconnected: unable to connect to renderer
(Session info: chrome=65.0.3325.181)
(Driver info: chromedriver=2.31.488763
Sample program
I've written a sample program to reproduce the error.
Please download it from my dropbox url: https://db.tt/HqUTMOKWBl
You can click the link and download 'TrialWebTestForInspection.zip'.
Please extract it in any arbitrary folder and find TrialWebTestForInspection.sln.
The solution consists of two projects, "TrialWebUnitTest" and "TrialWebUnitTestRunner".
The first one is MS Unit Test, and you can run 3 test methods from Visual Studio Test Explorer.
The 3 test methods are very simple. They just launch the browser correspond to the webdriver, and navigate to Selenium HQ site.
The other project is a WindowsForm application which provide a very simple test runner.
It kicks the test methods in previous test project.
When you choose the test method using IE or FireFox driver, it works fine.
On the other hand, when you choose Chrome driver test, it thows exception which I mentioned above.
Things I'd like to know.
First I'd like to know, if it is a bug of current Chrome driver version, or it is a part of specification.
Then I'd like to know, if there is a way to avoid this problem or not.
What I'm afraid of is the possibility that IWebDriver specification originally does not support correct action whent it is run by reflection.
spec of sample program
.NET Framework version 4.6.1
nuget package
MSTest.TestFramework.1.2.0 MSTest.TestAdapter.1.2.0
Selenium.WebDriver.3.11.0 Selenium.WebDriver.ChromeDriver.2.37.0
Selenium.WebDriver.IEDriver.3.11.1 Selenium.Firefox.WebDriver.0.20.0
Chrome Browser version 65.0.3325.181(Official Build)(64 bit)
The problem was solved. Please refer to this.
The custom TestRunner application didn't refer to the latest chrome-driver version. I had to install selenium.webdrivers not only to the testclass, but also to the testrunner program.
For further information, please refer to the following issue in GitHUB.
https://github.com/SeleniumHQ/selenium/issues/5705
So I just got a hold of WatiN and wanted to do some automated acceptance tests.
I've got resharper, as well as Nunit and WatiN using NuGet manager. Changed the reference Interop.SHDocVw property of Embed Interop to false so everything works fine, the browser shows up, writes text in a box(kinda fast so I only see the end result and no the typing which I don't know if it's possible to slow it down), clicks a button, etc.. Well... fine until I add an Assert in the end of my Test. It fails.
It kinda looks like the browser is closing before the test finishes. I've used the WaitForComplete() method but it looks like it doesn't do anything. Is there a way to fix that?
using System.Threading;
using NUnit.Framework;
using WatiN.Core;
namespace Testy
{
[TestFixture]
[Apartment(ApartmentState.STA)]
public class UnitTest2
{
[Test]
public void SearchForWatiNOnGoogle()
{
using (var browser = new IE("google.com"))
{
browser.TextField(Find.ByName("q")).TypeText("WatiN");
browser.Button(Find.ByName("btnG")).Click();
Assert.IsTrue(browser.ContainsText("WatiN"));
}
}
}
}
And this is what I tried but with no better results.
[Test]
public void SearchForWatiNOnGoogle()
{
using (var browser = new IE("google.com"))
{
browser.TextField(Find.ByName("q")).TypeText("WatiN");
browser.WaitForComplete(4000);
browser.Button(Find.ByName("btnG")).Click();
browser.WaitForComplete(4000);
Assert.IsTrue(browser.ContainsText("WatiN"));
browser.Close();
}
}
Try to set the autoclose to false ie
browser.AutoClose = false;
however - that project hasn't been active in years. What about the functionality built right into Visual Studio for this for UI Automation?
I've Created a Music Player Using Visual Studio 2012 WindowsForm C#, Now I want to play/add songs from Windows Explorer as any other Player(Windows Media Player,Winamp,MpcStar,VLC...) does! so I think it wouldn't be real hard! some of these programs are simple!
so for example: I select 3 Songs in a directory in explorer and right click on them and select "Play With " and then they should use my application add function to be added to playlist and start playing! if User Press Enter key also should do this operation!
If User Select "Add to Playlist" the songs should just added to my playlist (not replace previous playlist songs)
I don't want you to create my program I just need an answer to know how can i get paths of all selected files by windows explorer context-menu!
*** I want to get all selected files path not just single file!
** UPDATE: I found the solution! I posted the answer below! hope it helps others too :)
ok Finally I've got the solution :)
this link helped me to get paths of selected files in explorer by clicking on a context-menu item:
.NET Shell Extensions - Shell Context Menus
real easy :)
Here's The Steps:
1) Download thee SharpShell library>>
Download the 'SharpShell Library' zip file at the top of the article and add a reference to the downloaded SharpShell.dll file.
or you can download it via Nuget:
If you have Nuget installed, just do a quick search for SharpShell and install it directly - or get the package details at https://www.nuget.org/packages/SharpShell.
Add the following references:
System.Windows.Forms
System.Drawing
Use these at top of your code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpShell;
using SharpShell.SharpContextMenu;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using SharpShell.Attributes;
Derive your Class From SharpContextMenu
Right click on the SharpContextMenu part of the line and choose Implement Abstract Class.
CanShowMenu
This function is called to determine whether we should show the Context Menu Extension for a given set of files. The files the user has selected are in the property SelectedItemPaths. We can check these file paths to see whether we actually want to show the menu. If the menu should be shown, return true. If not, return false.
CreateMenu
This function is called to actually create the Context Menu. A standard WinForms ContextMenuStrip is all we need to return.
Here's the whole namespace SourceCode:
namespace CountLinesExtension
{
[ComVisible(true)]
[COMServerAssociation(AssociationType.ClassOfExtension, ".txt")]
public class Class1 : SharpContextMenu
{
protected override bool CanShowMenu()
{
// We will always show the menu.
return true;
//throw new NotImplementedException();
}
protected override ContextMenuStrip CreateMenu()
{
// Create the menu strip.
var menu = new ContextMenuStrip();
// Create a 'count lines' item.
var itemCountLines = new ToolStripMenuItem
{
Text = "Count Lines"
};
// When we click, we'll call the 'CountLines' function.
itemCountLines.Click += (sender, args) => CountLines();
// Add the item to the context menu.
menu.Items.Add(itemCountLines);
// Return the menu.
return menu;
//throw new NotImplementedException();
}
private void CountLines()
{
// Builder for the output.
var builder = new StringBuilder();
// Go through each file.
foreach (var filePath in SelectedItemPaths)
{
// Count the lines.
builder.AppendLine(string.Format("{0} - {1} Lines",
Path.GetFileName(filePath), File.ReadAllLines(filePath).Length));
}
// Show the ouput.
MessageBox.Show(builder.ToString());
}
}
}
Next, we must give the assembly a strong name. There are ways around this requirement, but generally this is the best approach to take. To do this, right click on the project and choose 'Properties'. Then go to 'Signing'. Choose 'Sign the Assembly', specify 'New' for the key and choose a key name. You can password protect the key if you want to, but it is not required
Now Install and register Shell Extension:
The regasm Tool
You can use the tool 'regasm' to install and register a shell extension. When using regasm, the shell extension will be installed into the registry (i.e. the Class ID of the COM Server will be put in the COM Server Classes section and associated with the path to the actual server file), it will also register the associations.
The Server Manager Tool
The Server Manager Tool is my preferred approach for installing/uninstalling and registering/unregistering, at least during development, because it lets you install and register as separate steps. It will also let you specify whether you're installing/uninstalling etc in 32 bit or 64 bit mode.
It was the whole Sample sourceCode. we can add any number of context-menu items, any function,any fileextension,etc.
For Example I'm gonna use '.mp3' FileExtensions and change Countlines Function to a function that will send SelectedItemPaths to playlist and the rest of operations.
Hope this help others too!