Docker compose does not work for Selenium CSharp as expected - c#

I have Docker for Windows on my machine and I want to start with one HUB 2 nodes at a ubuntu client, one for FireFox and one for Chrome, and both are running in parallel. There for I have A CSharp code, It runs Perfectly Whaen I run the : HUB, node-chrome-debug, and node-firefox-debug seperatelly, one by one like this from Windows POWERSHELL: :
docker run -d -p 4446:4444 --name selenium-hub -P selenium/hub
docker run -d -P --link selenium-hub:hub selenium/node-chrome-debug
docker run -d -P --link selenium-hub:hub selenium/node-firefox-debug
But If I want do the SAME with Docker compose file. I come in problems:
The Question is : What is wrong with this Docker compose file:
version: '3'
services:
seleniumhub:
image: selenium/hub
ports:
- 4444:4444
firefoxnode:
image: selenium/node-firefox-debug
ports:
- 4577
links:
- seleniumhub:hub
chromenode:
image: selenium/node-chrome-debug
ports:
- 4578
links:
- seleniumhub:hub
I'm Running The following CSharp code:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NUnit.Framework;
using OpenQA.Selenium;
using System;
using Assert = NUnit.Framework.Assert;
namespace SeleniumParalelTest
{
[TestFixture]
[Parallelizable]
public class FirefoxTesting : Hooks
{
public FirefoxTesting() : base(BrowserType.Firefox)
{
}
[Test]
public void FirefoxGoogleTest()
{
Driver.Navigate().GoToUrl("https://www.selenium.dev/");
Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(20);
Driver.FindElement(By.XPath("//*[#id='banner-blm']/h2/strong"));
System.Threading.Thread.Sleep(20000);
}
}
[TestFixture]
[Parallelizable]
public class ChromeTesting : Hooks
{
public ChromeTesting() : base(BrowserType.Chrome)
{
}
[Test]
public void ChromeGoogleTest()
{
Driver.Navigate().GoToUrl("https://www.selenium.dev/");
Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(20);
Driver.FindElement(By.XPath("//*[#id='banner-blm']/h2/strong"));
System.Threading.Thread.Sleep(20000);
}
}
}

Related

Starting a c# service with sc

Im writing a small selfcontained service for windows and macos using worker service template in c# visual studio.
Its using the same Codebase hence the check in the Program.cs
I've written the service, and it works on windows, when started from within visual studio.
I've published it using
dotnet publish .\WorkerServiceTest2\ -c Release -r win-x64 -- self-contained true /p:PublishSingleFile=true /p:PublishedTrimmed=true
and tried to install it using
runas /user:MYUSERNAME "sc.exe create WorkerServiceTest2 c:\Users\MYYUSERNAME\Documents\bla\bla\bla\WorkerServiceTest2.exe"
But it does not show up in the services list, and
sc.exe start WorkerServiceTest2
says this service is not installed.
Is there anywhere i can see how the sc.exe create worked out ?
Or perhaps someone can see what I'm doing wrong ?
Sincerely Thankyou
My Service Program.cs looks like this
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Runtime.InteropServices;
namespace WorkerServiceTest2
{
public class Program
{
public static void Main(string[] args)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)){
Console.WriteLine("WinOS");
CreateHostBuilderWin(args).Build().Run();
} else
{
Console.WriteLine("MacOS");
CreateHostBuilderMac(args).Build().Run();
}
}
private static void configureServices(HostBuilderContext context, IServiceCollection services)
{
services.AddHostedService<Worker>();
}
public static IHostBuilder CreateHostBuilderWin(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
public static IHostBuilder CreateHostBuilderMac(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(configureServices);
}
}
My Worker.cs looks like this
using Microsoft.Extensions.Hosting;
using System.Threading;
using System.Threading.Tasks;
using WorkerServiceTest2.SocketService;
namespace WorkerServiceTest2
{
public class Worker : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
//Her skal business logic være.
SocketServer socketServer = new SocketServer();
await socketServer.start();
}
}
}
}
This is a script that you can use. It will check if the service is installed or not. If it already exists, it will uninstall it and install the new one. Save it as MyScript.ps1 (or your own preference) and run like:
.\MyScript.ps1 -serviceName name_of_service -serviceUsername some_username -servicePassword some_password -binaryPath "C:\yourProgram.exe"
Script:
# Sample: howto run ps-script from power-shell:
#.\Install-WindowsService_v3.ps1 -serviceName aTestservice -serviceUsername some_username -servicePassword some_password -binaryPath "C:\yourProgram.exe"
param
(
[string]$serviceName,
[string]$serviceUsername,
[string]$servicePassword,
[string]$binaryPath,
[string]$startupType='Automatic',
[string]$dependsOn
)
$secpasswd = ConvertTo-SecureString $servicePassword -AsPlainText -Force
Write-Output "########################################"
Write-Output "Starting installation of windows service."
Write-Output "[serviceName] = $serviceName"
Write-Output "[serviceUsername] = $serviceUsername" -verbose
Write-Output "[binaryPath] = $binaryPath"
#Check Parameters
if (!$binaryPath) { throw "[binaryPath] parameter missing" }
if ((Test-Path $binaryPath)-eq $false)
{
Write-Output "Path doesn't exist: $binaryPath"
Write-Output "Service will not be installed."
throw [System.IO.FileNotFoundException] "$binaryPath doesn't exist."
}
# verify if the service already exists, and if yes remove it first
if (Get-Service $serviceName -ErrorAction SilentlyContinue)
{
Stop-Service -Name $serviceName
# using WMI to remove Windows service because PowerShell does not have CmdLet for this
$serviceToRemove = Get-WmiObject -Class Win32_Service -Filter "name='$serviceName'"
$serviceToRemove.delete()
Write-Output "Service $serviceName was stopped and uninstalled."
}
else
{
Write-Output "Service didn't exist on the server"
}
if ($startupType -eq "AutomaticDelayedStart" )
{
$startupType = "Automatic"
$enableDelayed = "true"
}
Write-Output "Installing service"
# creating credentials which can be used to run my windows service
$mycreds = New-Object System.Management.Automation.PSCredential ($serviceUsername, $secpasswd)
# creating windows service using all provided parameters
New-Service -name $serviceName -binaryPathName $binaryPath -displayName $serviceName -startupType $startupType -credential $mycreds -DependsOn $dependsOn
# Set "automatic delayed" after service was installed, since it is not a valid argument when using "New-Service"
if ($enableDelayed -eq "true" )
{
$command = "sc.exe config $serviceName start= delayed-auto"
$Output = Invoke-Expression -Command $Command -ErrorAction Stop
if($LASTEXITCODE -ne 0){
Write-Host "$Computer : Failed to set $serviceName to delayed start.
More details: $Output" -foregroundcolor red
$failedcomputers +=$ComputerName
} else {
Write-Host "$Computer : Successfully changed $serviceName
to delayed start" -foregroundcolor green
$successcomputers +=$ComputerName
}
}
# verify if the service exists after installation
if (Get-Service $serviceName -ErrorAction SilentlyContinue)
{
Write-Output "Installation complete."
}
else
{
throw "Installation failed."
}
Write-Output "########################################"
Also, in all my application I start them up like so:
static async Task Main(string[] args)
{
isService = !(Debugger.IsAttached || args.Contains("--console"));
IWebHost host = CreateWebHostBuilder(args).Build();
if (isService)
{
var hostService = new MyCustomWebService(host);
ServiceBase.Run(hostService);
}
else
{
await host.RunAsync();
}
}
public class MyCustomWebService: WebHostService
{
private ILogger<MyCustomWebService> logger;
public MyCustomWebService(IWebHost host) : base(host)
{
var loggerFactory = host.Services.GetService<ILoggerFactory>();
logger = loggerFactory.CreateLogger<MyCustomWebService>();
logger.LogInformation("Starting...");
}
protected override void OnStopped()
{
logger.LogInformation("Will stop now.");
base.OnStopped();
}
}
It requires Microsoft.AspNetCore.Hosting.WindowsServices
Further recommended reading:
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-5.0&tabs=visual-studio
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.windowsservices?view=aspnetcore-5.0

Unable to detect selector element in a ionic5 application using appium & c#

using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Remote;
using System;
using System.Threading;
using Xunit;
namespace XUnitTestProject2
{
public class UnitTest1
{
[Fact]
public void Test1()
{
Thread.Sleep(3000);
var driver = InitiliseDriver();
//Login Page
driver.FindElement(By.Id("username")).SendKeys("TestUser");
driver.FindElement(MobileBy.Id("password")).SendKeys("newpassword");
driver.FindElement(MobileBy.Id("91268f5d-d21e-4ef5-9886-c1d19f2799a7")).Click();
}
private RemoteWebDriver InitiliseDriver()
{
//Set the capabilities
DesiredCapabilities cap = new DesiredCapabilities();
cap.SetCapability("platformName", "Android");
cap.SetCapability("platformVersion", "9.0");
cap.SetCapability("app", "C:\\Users\\jamesa\\Downloads\\app-debug.apk");
//cap.SetCapability("automationName", "uiautomator2");
return new RemoteWebDriver(new Uri("http://127.0.0.1:4723/wd/hub"), cap);
}
}
}
My nuget packages are Appium.WebDriver(4.1.1); Microsoft.Net.Test.Sdk(16.0.1); Selenium.Support(3.141.0); Selenium.WebDriver(3.141.0); Xunit(2.4.0); Xunit.runner.visualstudios(2.4.0); MSTest.TestAdapter(2.1.2); MSTest.TestFramework(2.1.2)
My Desired Capabilities are platformName- Text- Android; platformVersion- Text - 9.0; app - Text - \\\
This is the session details I am getting I do have selector ID but the server is not picking it
Note: - I am able to launch the application successfully but the server is unable to pick the element. - The application is built in an Ionic way (Ionic 5)
You need to set your driver context to WEBVIEW, ionic builds apps with webview (not native), also you might want to build your app in debug mode. Here is more details on testing hybrid applications with appium.
In your case you would need to add something like this, before executing the tests
driver.context("WEBVIEW");

Run Selenium Grid C# Project in Visual Studio

I'm implemented Nunit selenium C# testing in visual studio (Console Application n Class Library). My project in visual studio is console application. I started the selenium grid using
java -Dwebdriver.gecko.driver="..\jar\geckodriver.exe" -Dwebdriver.chrome.driver="..\jar\chromedriver.exe" -Dwebdriver.ie.driver="..\jar\IEDriverServer.exe" -jar ..\jar\selenium-server-standalone-3.14.0.jar -role hub -port 4444
Code:
using Automation_Framework.Manager;
using NUnit.Framework;
using OpenQA.Selenium;
using System;
using System.Collections.Generic;
using System.Text;
namespace Automation_Framework.TestManager
{
[TestFixture]
class ChromeTestManager
{
private WebDriverManager webDriverManager;
private IWebDriver driver;
public ChromeTestManager()
{
webDriverManager = new WebDriverManager();
}
[SetUp]
public void setup()
{
webDriverManager.createDriver("chrome");
driver = webDriverManager.getDriver();
}
[Test]
public void test()
{
driver.Url = "http://www.google.com.my";
driver.Navigate();
}
[TearDown]
public void shutdown()
{
driver.Close();
}
}
}
I had tried execute using Test Explorer but it does not open any browser. I"m following this tutorial.
Questions:
How to run the project with browser open and see all actions?
How to run using Nunit-console-runner.
Please help me. Thanks.
I assume that:
1. You have tried your code locally and your test is opening the browser when you run it on your machine without the grid.
2. Your nodes are set up and registered with the hub.
You need to:
1. Use RemoteWebDriver:
var uri = 'uri_to_your_grid_hub';
var capabilities = new ChromeOptions().ToCapabilities();
var commandTimeout = TimeSpan.FromMinutes(5);
var driver = new RemoteWebDriver(new Uri(uri),capabilities,commandTimeout)
Add the attribute to a class: [Parallelizable(ParallelScope.Self)] in order to run your tests in parallel with other test classes.
In order to verify whether the hub is running, open the browser and navigate to http://localhost:4444 on the hub machine.
Sources:
How can I run NUnit(Selenium Grid) tests in parallel?
Selenium Grid in C#
Useful C# WebDriver examples
Selenium Grid set up
I haven't used grid in .Net but here my answer:
your command is just register a hub, which needs to keep running (open a browser and test it is working)
you need to register your nodes under that hub (different ports) (open a browser and test it is working)
in your code, you should use "RemoteWebDriver" to connect to the hub.
something along these lines (it is in java but I hope it gives you a starting point)
public class Gmail
{
public WebDriver driver=null;
#Parameters("browser") //testng.xml
#Test()
public void GmailTest(String browser)
{
System.out.println("Gmail " + browser);
// RemoteWebdriver
DesiredCapabilities cap = null;
if(browser.equals("firefox")){
cap = DesiredCapabilities.firefox();
cap.setBrowserName("firefox");
cap.setPlatform(Platform.ANY);
}else if (browser.equals("iexplore")){
cap = DesiredCapabilities.internetExplorer();
cap.setBrowserName("iexplore");
cap.setPlatform(Platform.WINDOWS);
}
driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"),cap);
driver.get("http://gmail.com");
driver.findElement(By.id("Email")).sendKeys("abcd");
driver.quit();
}
I hope this helps.good luck

Why FileSystemWatcher doesn't work in Linux container watching Windows volume

Given the program:
using System;
using System.IO;
namespace fsw_bug_poc
{
class Program
{
private static FileSystemWatcher _fileSystemWatcher;
static void Main(string[] args)
{
_fileSystemWatcher = new FileSystemWatcher("Watched", "*.*");
_fileSystemWatcher.Changed += Notify;
_fileSystemWatcher.Created += Notify;
_fileSystemWatcher.Deleted += Notify;
_fileSystemWatcher.Renamed += Notify;
_fileSystemWatcher.IncludeSubdirectories = true;
_fileSystemWatcher.EnableRaisingEvents = true;
Console.ReadKey(false);
}
private static void Notify(object sender, FileSystemEventArgs e)
{
Console.WriteLine($"{e.FullPath} {e.ChangeType}");
}
}
}
The Dockerfile:
FROM mcr.microsoft.com/dotnet/core/runtime:2.2-stretch-slim AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY ["fsw-bug-poc.csproj", ""]
RUN dotnet restore "fsw-bug-poc.csproj"
COPY . .
WORKDIR "/src/"
RUN dotnet build "fsw-bug-poc.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "fsw-bug-poc.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
RUN mkdir -p /app/Watched
VOLUME /app/Watched
ENTRYPOINT ["dotnet", "fsw-bug-poc.dll"]
According to this link adding ENV DOTNET_USE_POLLING_FILE_WATCHER=true to the Dockerfile fixes the FileSystemWatcher not working inside the container.
Even with this fix, FileSystemWatcher will not work when running a Linux container on Windows and mounting a shared driver to a volume:
docker build -t fsw-bug-poc .
docker run -it --rm -v C:\Shared:/app/Watched fsw-bug-poc
Modifying a file inside the container:
Modifying files in the shared volume folder:
Nothing happens!!
Can someone explain what is going on? The FileSystemWatcher is using a polling strategy, so it should work the same way, shouldn't it?
Switching to PhysicalFileProvider did the job. It seems to be a more portable implementation for file system watching strategies.
The current implementation of PhysicalFileProvider supports the DOTNET_USE_POLLING_FILE_WATCHER environment variable. I couldn't find any reference of it in FileSystemWatcher implementation.
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using System;
using System.IO;
namespace fsw_bug_poc
{
class Program
{
private static PhysicalFileProvider _fileProvider;
private static IChangeToken _fileChangeToken;
static void Main(string[] args)
{
_fileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "."));
WatchForFileChanges();
Console.ReadKey(false);
}
private static void WatchForFileChanges()
{
_fileChangeToken = _fileProvider.Watch("*.*");
_fileChangeToken.RegisterChangeCallback(Notify, default);
}
private static void Notify(object state)
{
Console.WriteLine("File change detected");
WatchForFileChanges();
}
}
}

Selenium cannot connect to localhost for testing ASP.NET

I'm writing GUI tests for an ASP.NET web application but Selenium can not seem to connect to the localhost. Every time I run the test case it loads the chrome browser, but I get the error "ERR_CONNECTION_REFUSED". I can connect to the localhost just fine for development, just not testing.
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
namespace MyApplication.Tests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void ButtonMenuDimensions_Chrome()
{
try
{
String url = "http://localhost:52956";
ChromeDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl(url);
driver.Manage().Window.Maximize();
String actualHeight = driver.FindElement(By.Id("menu")).GetCssValue("height");
Console.WriteLine("Actual Height: " + actualHeight);
String expectedHeight = "450px";
String actualWidth = driver.FindElement(By.Id("menu")).GetCssValue("width");
String expectedWidth = "200px";
Assert.AreEqual(expectedHeight, actualHeight);
Assert.AreEqual(expectedWidth, actualWidth);
driver.Close();
driver.Dispose();
}
catch
{
Console.WriteLine("Error executing test case: Dimensions");
}
}
}
}
When I open up the output for this test case I am getting
Error executing test case: Dimensions
I suspect you're running the app on iis express, you will need to make sure this is running when your test are by having the ASP website running/debugging in VS.
If you hit the URL http://localhost:52956 without running the ASP website can you still hit it?

Categories

Resources