Main features:
- User-oriented API for Selenium Webdriver (code like speak common English)
- Ajax support (Smart implicit waiting and retry mechanism)
- PageObjects support (all elements are lazy-evaluated objects)
Tests with Selene can be built either in a simple straightforward "selenide' style or with PageObjects composed from Widgets i.e. reusable element components.
For docs see tests in the NSeleneTests project for now;)
-
Upcomig version to use is just released 1.0.0-alpha14
- targets netstandard2.0
- wraps Selenium >= 4.9.*
- it differs from 0.0.0.7 in the following:
- repacked in sdk-style format
- removed things marked as obsolete til 0.0.0.7
- upgraded waiting of commands, error messages, thread local configuration, etc. (see CHANGELOG for more details)
- it should be
- faster,
- more stable/less-flaky (with implicit waiting till no overlay-style pre-loaders)
- more friendly to parallelisation in context of configuration,
- more customizable on elements level (not just global)
- it should be
- can be installed by:
dotnet add package NSelene --version 1.0.0-alpha07
- migration guide from 1.0.0-alpha03 to 1.0.0-alpha05
- upgrade and check your build
- refactor your custom conditions:
- if you have implemented your own custom conditions by extending e.g.
Condition<SeleneElement>
- you will get a compilation error – to fix it:
- change base class from
Condition<SeleneElement>
toDescribedCondition<SeleneElement>
- remove
public override string Explain()
and leavepublic override string ToString()
instead - if you use anywehere in your code an
Apply
method on condition of typeCondition<TEntity>
- you will get an obsolete warning
- refactor your code to use
Invoke
method, taking into account that- anytime Apply throws exception - Invoke also throws exception
- anytime Apply returns false - Invoke throws exception
- anytime Apply returns true - Invoke just passes (it's of void type)
- refactor your code to use
- you will get an obsolete warning
- change base class from
- you will get a compilation error – to fix it:
- if you have implemented your own custom conditions by extending e.g.
- refactor obsolete things, like:
Configuration.WebDriver
=>Configuration.Driver
S("#element").ShouldNot(Be.*)
toS("#element").Should(Be.Not.*)
S("#element").ShouldNot(yourCustomCondition)
toS("#element").Should(yourCustomCondition.Not)
- etc
- refactor your custom conditions:
- take into account, that some "internal" methods of 1.0.0-alpha05 were made public for easiser experimental testing in prod:),
but still considered as internal, that might change in future
such methods are named with
_
prefix, following kind of Python lang style of "still publically accessible private" methods:) use such methods on your own risk, take into account that they might be marked as obsolete in future yet, they will be eather renamed or made completely internal till stable 1.0 release;) read CHANGELOG for more details.
- upgrade and check your build
-
Latest stable version: 0.0.0.7
- targets net45
- it is main version used by most nselene users during during last 4 years
- there were not so much users, but even some small companies use it for their projects
- so it was proven to be stable for production use
- its sources can be found at 0.x branch
See changelog for more details.
Find an example of NSelene usage in this template project.
Below you can find a short overview:
[TestFixture]
public class BrowserTest
{
[SetUp]
public void InitDriver()
{
Configuration.Driver = new ChromeDriver();
// a handy option to enable automatic waiting for no overlay in web tests
Configuration.WaitForNoOverlapFoundByJs = true;
}
[TearDown]
public void QuitDriver()
{
Configuration.Driver.Quit();
}
}
Tests may look like this in a so-called "straightforward" style:
[TestFixture]
public class TodoMvcShould : BrowserTest
{
[Test]
public void CompleteTask()
{
// ensure you added `using static NSelene.Selene;` in the beginning of a file ;)
Open("http://todomvc.com/examples/emberjs/");
S("#new-todo").SetValue("a").PressEnter();
S("#new-todo").SetValue("b").PressEnter();
S("#new-todo").SetValue("c").PressEnter();
SS("#todo-list>li").FindBy(Have.ExactText("b")).Find(".toggle").Click();
SS("#todo-list>li").By(Have.CssClass("completed")).Should(Have.ExactTexts("b"));
SS("#todo-list>li").By(Have.No.CssClass("completed")).Should(Have.ExactTexts("a", "c"));
}
}
or with PageObjects:
using NUnit.Framework;
using Web.Tests.Model;
namespace Web.Tests
{
public class SearchEnginesShouldSearch : BrowserTest
{
[Test]
public void Ecosia()
{
Www.ecosia.Open();
Www.ecosia.Search("nselene dotnet");
Www.ecosia.Results.ShouldHaveSizeAtLeast(5)
.ShouldHaveText(0, "Consise API to Selenium for .Net");
Www.ecosia.Results.FollowLink(0);
Www.github.ShouldBeOn("yashaka/NSelene");
}
}
}
where the Ecosia page object may look like this:
namespace Web.Tests.Model.Pages
{
public class Ecosia
{
public Results Results => new Results(SS(".js-result"));
public void Open()
{
Selene.Open("https://www.ecosia.org/");
}
public void Search(string text)
{
S(By.Name("q")).Type(text).PressEnter();
}
}
public class Github
{
public void ShouldBeOn(string pageTitleText)
{
Selene.WaitTo(Match.TitleContaining(pageTitleText));
}
}
}
// ...
namespace Web.Tests.Model.Common
{
public class Results
{
SeleneCollection list;
public Results(SeleneCollection list)
{
this.list = list;
}
public Results ShouldHaveSizeAtLeast(int number)
{
list.Should(Have.CountAtLeast(number));
return this;
}
public Results ShouldHaveText(int index, string value)
{
list[index].Should(Have.Text(value));
return this;
}
public void FollowLink(int index)
{
list[index].Find("a").Click();
}
}
}
// ...
namespace Web.Tests.Model
{
class Www
{
public static Duckduckgo duckduckgo = new Duckduckgo();
public static Ecosia ecosia = new Ecosia();
public static Github github = new Github();
}
}
NSelene has a flexible way to locate elements by breakig long especially xpath selectors to smaller parts, like in:
SS("#list-item").FindBy(Have.CssClass("specific")).Find(".inner-element").click()
This allows to idetify more precisely which part was broken on failure.
S
, SS
also supports xpath selectors:
SS("(//h1|//h2)[contains(text(), 'foo')]").Should(Have.Count(10));
NSelene can be easily integrated into existing selenium based frameworks, because it is object-oriented by its nature. It provides a Consice API to Selenium via both "OOP" (SeleneDriver
class) and "static utils" wrappers (Selene
static class) over WebDriver. Because of the latter, NSelene also supports creation of "more than one driver per test". It can be rarely useful, but sometimes it "saves the life".
Feel free to share your thoughts and file an issue on github if you need something.
Before implementing your ideas, it is recommended first to create a corresponding issue and discuss the plan to be approved;) Also consider first to help with issues marked with help wanted label ;)
If you are a beginner consider starting with issues markd as good first issue
Target framework is .Net Standard 2.0
To build from the command line you need dotnet
2.0 and higher
Probably you will need your favourite code editor. Find some examples below:
- Visual Studio 2017+, VS Code or JetBrains Rider
- Visual Studio for Mac, VS Code or JetBrains Rider
Before doing anything it's good to just clone the project via git clone https://github.com/yashaka/NSelene.git
and play with it. Build, run tests, etc. For command line use dotnet build
, or build solution using your code editor.
- If yet it does not exist, add a "feature request" Issue to this project. (assume it's number is
<ISSUE-NUMBER>
) - Discuss its need and possible implementation. And once approved...
- Fork the project (https://github.com/[my-github-username]/NSelene/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am '#<ISSUE-NUMBER>: message described in short what was done'
) - If you forget to add something important, add it and include into the same commit by using `git add . && git commit --amend -m "#: "
- Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request`
- Wait for PR Riview and pass it if requested.
- the version is bumped in the
NSelene.csproj
to the next one, comparing to the peviously released version. - the changelog has a section for the current version (to be released) with list of all features implemented since the previous version was released
- you can check the commits history and closed issues since previous release
- the readme is updated if needed
- tests pass
dotnet test
- the corresponding git tag with current version number and description (should reflect the changelog) is added
dotnet build -c Release
dotnet nuget push bin/Release/NSelene<VERSION>.nupkg -k <KEY> -s https://api.nuget.org/v3/index.json