Enable C# Microsoft developers to use Selenium test infrastructures on Alt-macOS
Overview
Here is a hands-on tutorial to learn Selenium using the C# language edited in Visual Studio on MacOS. This an “immersion” approach as if you just got hired and are looking at a fully developed set of code to modify.
A lot of thought has gone into sequencing topics here so you learn easier, in less time.
The pre-requisite to this is the “start from scrach” approach of courses such as the one on Udemy from UltimateQA filmed 2015 by Nikolay Advolodkin (@Nikolay_A00, Facebook) and Dr. Tiffany Ford (rhysma@live.com) who teaches C#. quizzes.
Why this?
Microsoft’s VSTS (Visual Studio Team Services) costs several thousand dollars while Selenium is free (open source).
Run several Selenium instances in parallel on publicly available swarm facilities such as SauceLabs, BrowserStack, Rainforest.qa, https://crossbrowsertesting.com, and Selenium Grid in-house.
Include the Neotys API so that when Selenium is run, NeoLoad automatically updates “user paths” (scripts) for load testing.
https://msdn.microsoft.com/en-us/library/ee308828(v=bts.10).aspx
Install Visual Studio IDE
The Community Edition of Visual Studio IDE can be used.
If you already have Visual Studio IDE installed, go here.
Mac install
-
Use https://aka.ms/vsmac to https://www.visualstudio.com/vs/visual-studio-mac/ VisualStudioInstaller.dmg (25.3 MB)
This is analogous to downloading Visual Studio for Windows at https://www.visualstudio.com/downloads
- In Downloads folder, invoke the installer.
-
Uncheck the Android, iOS, macOS platforms, for 774 MB download, which takes a long time.
While you wait, look at the documentation at https://docs.microsoft.com/en-us/visualstudio/mac/
This IDE replaced Xamarin Studio as a full-featured IDE on Mac. But its Developer Center” still references Xamarin.
I kept getting an System.AggregateException”, “Xamarin.iOS 10.12.0.20 needs to be installed”.
So I had to download VisualStudioForMac-7.1.0.1297.dmg (290 MB). and then drag and drop the Visual Studio for Mac icon to the Applications folder.
-
Sign in and Activate license for Professional/Enterprise features:
https://docs.microsoft.com/en-us/visualstudio/mac/signing-in
https://docs.microsoft.com/en-us/visualstudio/mac/activation
Problems reported are at: https://developercommunity.visualstudio.com/spaces/41/index.html
To report a problem with Visual Studio for Mac: https://developercommunity.visualstudio.com/content/problem/post.html?space=41&inRegister=true
Windows install
Get Sample Selenium Code
-
Fork the excellent sample code at:
-
Assuming you have Git client installed, download the repo from your account. For example:
git clone https://github.com/wilsonmar-jetbloom/Onty.SeleniumTest.Webmail.git
- Use MacOS Finder or Windows Explorer to view the folder.
-
Delete the .vs folder so that the solution is not opened using them.
NOTE: From the root is a .vs folder which leads to a binary file .suo. This file contains user preference configurations specific to each machine. So although it is recreated automatically by Visual Studio, recreation resets metadata such as whether the project is loaded/unloaded at any given time. So its name should be specified in .gitignore and not pushed to GitHub.
Install app.config Developer Pack
-
Open a text editor and navigate into folder “Onty.SeleniumTest.Webmail”.
-
Open file app.config to see:
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
-
Get it.
On Windows:
Click “Download” at this page
NDP462-DevPack-KB3151934-ENU.exe
Microsoft .NET 4.62 Developer Pack
https://www.microsoft.com/net/targeting
http://getdotnet.azurewebsites.net/target-dotnet-platforms.html
On Mac:
https://www.microsoft.com/net/core#macos Click “Download .NET Core SDK” for file: dotnet-sdk-2.0.0-osx-gs-x64.pkg (133 MB)
NOTE: .NET Core is a newer approach than .NET Framework for server applications. .NET Core provides support for cross-platform development (Windows, Linux, and macOS) within Docker containers.
But .NET Framework libraries are still used for apps using third-party .NET libraries or NuGet packages not available for .NET Core.
http://dot.net provides a bash console
Install WebDrivers
Install WebDrivers on Windows
In app.config
:
<setting name="PathFirefox" serializeAs="String"> <value>C:\Program Files\Mozilla Firefox\firefox.exe</value> </setting> <setting name="WebDriverType" serializeAs="String"> <value>phantomjs</value>
See README
Processing of this results in WebDriver executables in the project’s root folder:
- WebDriver.dll
- WebDriver.Support.dll
- nunit.framework.dll
- chromedriver.exe
- geckodriver.exe (for Mozilla Firefox)
- IEDriverServer.exe
- phantomjs.exe
Install WebDrivers on MacOS
.dll and .exe are for Windows only and don’t work on a Mac.
So we need to:
-
Use https://www.npmjs.com/package/webdriver-manager
npm install -g webdriver-manager
-
download the selenium server jar and chromedriver binary:
webdriver-manager update
The response:
/Users/mac/.npm-packages/bin/webdriver-manager -> /Users/mac/.npm-packages/lib/node_modules/webdriver-manager/bin/webdriver-manager + webdriver-manager@12.0.6 added 96 packages in 26.426s
-
Start Selenium Server attached to foreground process:
webdriver-manager start
Alternately, start in background:
webdriver-manager start --detach
The response:
webdriver-manager: using global installed version 12.0.6 [21:04:30] I/file_manager - creating folder /Users/mac/.npm-packages/lib/node_modules/webdriver-manager/selenium [21:05:04] I/update - chromedriver: unzipping chromedriver_2.32.zip [21:05:04] I/update - chromedriver: setting permissions to 0755 for /Users/mac/.npm-packages/lib/node_modules/webdriver-manager/selenium/chromedriver_2.32 [21:05:47] I/update - geckodriver: unzipping geckodriver-v0.18.0.tar.gz [21:05:47] I/update - geckodriver: setting permissions to 0755 for /Users/mac/.npm-packages/lib/node_modules/webdriver-manager/selenium/geckodriver-v0.18.0
-
Open browser to http://localhost:4444/wd/hub
-
Stop Selenium Server if opened in background process:
webdriver-manager stop
Install WebDrivers On a Mac
-
TODO: On a Mac, change “C:\Program Files\Mozilla Firefox\firefox.exe” to ???
brew install selenium-server-standalone
-
Look into what is installed:
cat $(which selenium-server)
Which yields:
#!/bin/bash exec java -jar /usr/local/Cellar/selenium-server-standalone/3.5.3/libexec/selenium-server-standalone-3.5.3.jar "$@"
-
The .jar contains a .plist file which defines the default port for the equivalent of:
selenium-server -port 4444
The response: Selenium Server is up and running
For more options:
selenium-server -help
Widen the window to see without wrapping:
Usage: <main class> [options] Options: --version, -version Displays the version and exits. Default: false -browserTimeout <Integer> in seconds : number of seconds a browser session is allowed to hang while a WebDriver command is running (example: driver.get(url)). If the timeout is reached while a WebDriver command is still processing, the session will quit. Minimum value is 60. An unspecified, zero, or negative value means wait indefinitely. Default: 0 -debug <Boolean> : enables LogLevel.FINE. Default: false -enablePassThrough <Boolean>: Whether or not to use the experimental passthrough mode. Defaults to true. Default: true -jettyThreads, -jettyMaxThreads <Integer> : max number of threads for Jetty. An unspecified, zero, or negative value means the Jetty default value (200) will be used. -log <String> filename : the filename to use for logging. If omitted, will log to STDOUT -port <Integer> : the port number the server will use. Default: 4444 -role <String> options are [hub], [node], or [standalone]. Default: standalone -timeout, -sessionTimeout <Integer> in seconds : Specifies the timeout before the server automatically kills a session that hasn't had any activity in the last X seconds. The test slot will then be released for another test to use. This is typically used to take care of client crashes. For grid hub/node roles, cleanUpCycle must also be set. Default: 1800
Other properties in app.config
NOTE: Having strings such as PageLoadDelay
in this file makes the solution more flexible than hard-coding into C# code. TODO: Additional variables include:
- PageLoadTimeout = 60,
- ScriptTimeout = 60,
- ElementsWaitTimeout = 60
-
Navigate into file ….csproj
The …..csproj.user ???
In Visual Studio
-
Within Windows Explorer or macOS Finder, double-click on the .sln solution file to open it within Visual Studio.
PROTIP: Inside the .sln file, the “Visual Studio 14” is marketed by Microsoft as “Visual Studio 2015”.
Restore NuGet Package Dependencies
-
To download component dependencies in appropriate locations, in the Solution Explorer tool window, right-click on References. On Windows: click Restore NuGet Packages
NOTE: This is similar to running Maven to process its pom.xml file. But Visual Studio uses the packages.config.
-
View file
package.config
containing:<package id="Chromium.ChromeDriver" version="2.27" targetFramework="net46" /> <package id="NUnit" version="3.6.0" targetFramework="net46" /> <package id="NUnit3TestAdapter" version="3.7.0" targetFramework="net46" /> <package id="Selenium.Support" version="3.0.1" targetFramework="net46" /> <package id="Selenium.WebDriver" version="3.0.1" targetFramework="net46" /> <package id="Selenium.WebDriver.PhantomJS" version="1.0.0.0" targetFramework="net46" /> <package id="WebDriver.GeckoDriver" version="0.13.0" targetFramework="net46" /> <package id="WebDriverIEDriver" version="2.45.0.0" targetFramework="net46" />
The id of each packages specifies what is downloaded from Microsoft’s NuGet Gallery, such as: https://www.nuget.org/packages/NUnit3TestAdapter
https://marketplace.visualstudio.com/items?itemName=NUnitDevelopers.NUnit3TestAdapter
Project Docs Notes
-
Open
Docs/notes.txt
to add txt about the effort.PROTIP: Add new text at the top. Begin each entry with a date such as “2017-09-23”.
-
Click “Step Into” to run the file one line of code at a time.
Properties of Domain
- Navigate into the Properties folder.
-
Notice file AssemblyInfo.cs says
"This package contains a set of automated functional tests (via Selenium) for a Simple Webmail System."
NOTE: There are various Designer.cs files which contain the declaration and initialization of UI controls and form layouts. File
Settings.Designer.cs
is generated by Visual Studio based on information in filesettings.settings
using the settings designer updated upon changes to the Project + Settings tab. To force re-generation, delete theSettings.designer.cs
file, then right-click on the settings.settings file and select “Run custom tool”. -
Notice file Settings.settings defines the app running in the Heroku cloud:
-
Click to open the sample app running on the Heroku cloud:
http://onty-webmail-ruby.herokuapp.com
(But you can set up the webmain app in your own server.)
Common PageObjects and annotations
-
Right-click to View Page Source to see the HTML, containing HTML such as this:
<a id="nav-Login" href="/accounts/login">login</a> or <a id="nav-Signup" href="/accounts/signup">create an account</a>.
-
Search for an attribute id “nav-Login” and open file
CommonPageElements.cs
to see it referenced:[FindsBy( How = How.CssSelector, Using = "a#nav-Login" )] [CacheLookup] protected IWebElement LinkLogin { get; set; }
PROTIP: The “FindsBy” with square brackets are compiler annotations used to reducing coding overhead. It is from the OpenQA.Selenium.Support.PageObjects.FindsByAttribute WebDriver which “Initializes a new instance of the FindsByAttribute class”.
The
LinkLogin
web element is defined by a getter and setter.Get CSS
-
Open a new browser window and construct the URL to view the CSS file. Combine the URL:
https://onty-webmail-ruby.herokuapp.com
and concatenate from the HTML:
/assets/application-12d67291afb2e5f2832d974ea0f4b04402dcd84deb0a3fc19ffcbfbcbf503fce.css
The response is minified to remove spaces and line breaks not necessary to the computer.
-
PROTIP: Copy all the CSS and paste it into a new window at:
Copy and paste the output to a text file so you can use your favorite editor to search in it.
Domain objects
- Navigate up and into the
Domain
folder that defines objects in the app’s domain. - File User.cs
- File Message.cs
-
File Folder.cs
-
View file
ATest.cs
which defines Setup and Teardown for all tests in each run.NOTE: Each .cs (C#) file within this folder specifies the folder name in its namespace:
namespace Onty.SeleniumTest.Webmail.Tests
[TestFixture]
is a compiler annotation.WebDriverFactory.GetWebDriver();
To see where this is defined:
Utils
-
Navigate up and into Utils folder.
Files here define utility functions:
-
Open
WebDriverFactory.cs
. The GetWebDriver function invokes depending on what value is defined for thewdt
variable. -
Open others:
- Rnd.cs for a rnd() random function based on a millisecond.
- ScreenShotUtil.cs for the TakeScreenshot() function.
- StringUtil.cs for IntToBase26() and MakeRandomString().
SignUp (several users)
File
TestData.cs
adds new users with hard-coded names and passwords.Within PageObjects, file
AccountsSignupPage.cs
Tests
-
Navigate into the
Tests
folder.BLAH: Name tests using action verbs such as: ???
- Landing
- File Tests_General.cs has Test_General_Menu() that logs in and checks the menu.
- Tests_Login.cs has Test_Login_Invalid() and Test_Login_Valid()
- Tests_Mailbox.cs has Test_Mailbox_Home(), Test_Mailbox_CreateFolder and Test_Mailbox_SendMessage()
- Tests_NotLoggedIn.cs has Test_NotLoggedIn_Home() to detect when “not-logged-in message is not displayed”.
App PageObjects
Test code reference objects defined in PageObjects.
The Common\APage.cs file defines the base class/
The CommonPageElements.cs file overrides APage:
public class CommonPageElements : APage
Other PageObjects reference CommonPageElements:
public class AccountsHomePage : CommonPageElements
### Build, Run, Troubleshoot
- Build the solution.
- Open Test Explorer tool window in Visual Studio,
-
Click Run All or Build icon.
Alternately, you can click on a single [TestMethod] and right-click to select “Run Tests” or hold down command/ctrl+R,T.
If it doesn’t run, we have a debugging session.
See debugging tips
Add your own
Here is a crucial aspect of this tutorial.
Add new field
Change text validated
Add new form
Re-use for other apps
The structure of application code provides a base for re-use to test other applications:
- Home
- Login
- Password
- Signup
Here is my plan to generate this set of files automatically.
Many functions are “boilerplate” that are the same for all applications.
PROTIP: The advantage of code generation is that tests would be based not just on what elements appears in the app, but also on what should be there based on design specs.
Moustache Templating
A templating program is used to replace static text with variables inserted in files, such as this, which is in most files:
`namespace Onty.SeleniumTest.Webmail.PageObjects`
`namespace Onty.SeleniumTest.\{\{AppShortName}}.PageObjects`
For more complex replacements:
`using Onty.SeleniumTest.Webmail.\{\{FolderAbove}};`
`public class \{\{ThisFolderName}} : CommonPageElements`
Yeoman code generator
We use Yeoman for adding logic to generate code. Just like JHipster does.
See https://docs.microsoft.com/en-us/aspnet/core/client-side/yeoman
Yeoman is a project scaffolding system for creating many kinds of applications.
The Yeoman generator for ASP.NET Core contains a variety of project templates for starting a new web, MVC, or console application.
To install Yeoman, use Node:
npm install -g yo bower
Alternatively, https://leaptest.com/pages/selenium-testing
https://www.codeproject.com/Articles/1074039/Generate-Csharp-Client-API-for-ASP-NET-Web-API
Selenium Learning Resources
http://courses.ultimateqa.com/courses/synchronization-techniques Selenium Webdriver Synchronization Techniques Course</a>
http://courses.ultimateqa.com/courses/parallel-testing-tutorial Introduction to Sauce Labs and Browser Stack</a> free tutorial