New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new SelenideDriver(new FirefoxDriver()).find("#element") syntax in addition to $("#element") #354
Comments
I still believe that using 2 browser windows in the same test is bad idea. But probably we will implement this feature request. Just because many people ask for this. |
I don't understand what you trying to say about Selenide. Any limitation Selenide has Selenium has as well. If you need to use two browser windows, then just like Selenium, you will need to create two If you need to use Selenide, you will need to assign each If you need to use the same Page Objects with multiple browsers, then the context must be set for each before instantiating it. Below is a JUnit example using a single Page Object between two different NOTE 1: Reference the NOTE 2: By doing this you will need to close the import static com.codeborne.selenide.Selenide.page;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.FindBy;
import com.codeborne.selenide.Selenide;
import com.codeborne.selenide.SelenideElement;
import com.codeborne.selenide.WebDriverRunner;
public class AppTest {
private WebDriver w1;
private WebDriver w2;
private WebDriver w3;
private ExamplePage ex1;
private ExamplePage ex2;
@Before
public void setUp() {
w1 = new FirefoxDriver();
w2 = new FirefoxDriver();
w3 = new FirefoxDriver();
WebDriverRunner.setWebDriver(w1);
ex1 = page(ExamplePage.class);
WebDriverRunner.setWebDriver(w2);
ex2 = page(ExamplePage.class);
}
@Test
public void test() {
WebDriverRunner.setWebDriver(w1);
Selenide.open("http://www.example.com");
Assert.assertTrue(Selenide.title().equals("Example Domain"));
WebDriverRunner.setWebDriver(w3);
Selenide.open("http://www.google.com");
Assert.assertTrue(Selenide.title().equals("Google"));
WebDriverRunner.setWebDriver(w2);
Selenide.open("http://www.example.com");
Assert.assertTrue(Selenide.title().equals("Example Domain"));
ex2.moreInfoLink.click();
Assert.assertTrue(Selenide.title().equals("IANA — IANA-managed Reserved Domains"));
WebDriverRunner.setWebDriver(w1);
ex1.moreInfoLink.click();
Assert.assertTrue(Selenide.title().equals("IANA — IANA-managed Reserved Domains"));
}
@After
public void tearDown() {
w1.close();
w2.close();
w3.close();
}
static class ExamplePage {
@FindBy(tagName = "a")
public SelenideElement moreInfoLink;
}
} It also seems the use case you desire wants an almost undetermined number of clients to be generated. Using reflection is probably the best way to spawn WebDriver instances and Page Objects. I agree with @asolntsev with the whole messiness of dealing with multiple browsers. You may need to look to performance testing software like Gatling |
@JasonTolotta Everything you wrote, I also mentioned in my post. And your example just reflects my note on the subject:
Pay attention to this part:
As I explained, your example is a BADly implemented test. Good test implementation should contain test logic, not TECHNICAL DETAILS like "switching drivers". Such test is too complicated and needs more time for support. It's also prone to errors when something changes in test logic. There are also a plenty of arguments in context of "good design", but this is just a test, not a "complicated software system" so I will leave them out of the board:) Taking this into account, I can't agree with:
Because Selenium is free of limitation - "overload your test with bulky technical details in context of driver management". Saying all this, I still completely agree with @asolntsev that
But sometimes, on some projects, you just have no other choice (except of "retire from work"), because of many things. And in such cases, you have to use selenium (some own selenium based framework) over selenide, if you still want to write "concise and easy to read and support" tests ... And it's a sad... I believe that if we make Selenide "more friendly" in this context, we can make it more popular, and so have more power to convince people that yeah,
|
And, by the way, there is one more use case for this feature. It is described here with examples in C#: https://github.com/yashaka/NSelene/tree/master/NSeleneExamples/TodoMVC/IntegratedToSeleniumBasedFramework The idea is the following. And let's assume that this selenium based framework is not good enough, some steps are not stable (because of e.g. Ajax problems), and engineers would like to switch to Selenide. But they have no time to "rewrite all old tests and pageobjects". And now, with current Selenide implementation the only option they have is:
But to achieve the goal 2 (fix unstable parts by using Selenide over own framework) they have to rewrite pageobject fully what is not a good choice taking into account our precondition. But if we add to Selenide a correspondent webdriver decorator, everything will become much smoother. Want to cover new webpage? - no problem, just add a pageobject in a normal "selenide way" with automatic driver management Want to fix some unstable step which uses Have problems with some Easy;) In this way, we will not only give Selenide as a "better tool for your next automation project", we also will sell it as a "better tool for your current automation project". I have trained a lot of my students to work with selenide (in addition to selenium). And many of them find new projects and face the "our own selenium based frameworks" and have to live in "hell" after come back from "paradise"... They have to support "legacy bulky not stable code" in the same "bulky" way. I believe that the proposed feature can really make their life much easier... |
One more use case for "bad test with two drivers":) A backend of some project will be completely refactored, completely:) So we may need some "acceptance tests" that should be fully of "black box" style, with no any dependence to backend. Such tests will be slow... And (recall example with social network from my first post) it will really save some execution time to optimise them via dealing with several opened browsers... |
Code examples for original post:
// somewhere in init
joeDriver = new FirefoxDriver();
bobDriver = new FirefoxDriver();
joePage = new Page(joeDriver);
bobPage = new Page(bobDriver);
joePage.open()
joePage.login("joe", "qwerty");
bobPage.open()
joePage.login("bob", "123456");
...
//in test "create post"
bobPage.createPost("red fox jumps over lazy dog");
joePage.stream.posts.first().shouldHave(text("red fox jumps over lazy dog")); vs // somewhere in init
joeDriver = new FirefoxDriver();
bobDriver = new FirefoxDriver();
joePage = new Page(joeDriver);
bobPage = new Page(bobDriver);
setDriver(joeDriver);
joePage.open();
joePage.login("joe", "qwerty");
setDriver(bobDriver);
bobPage.open();
joePage.login("bob", "123456");
...
//in test "create post"
setDriver(bobDriver);
bobPage.createPost("red fox jumps over lazy dog");
setDriver(joeDriver);
joePage.stream.posts.first().shouldHave(text("red fox jumps over lazy dog")); |
@JasonTolotta
seems to me as "boilerplate" code. Solution is far away from being "elegant" and "concise". Second, your wrapper can "implicitly" switch drivers only during navigation. This means that the test will still contain the same "technical details" - this time - The one idea is to provide a solution that can remove "technical details" from "test logic" for tests working with "Several browsers" and built with "pageobject steps". The second idea is to provide solution that can integrate selenide into existing selenium based framework taking into account that the majority of such frameworks uses "driver as a state of PageObject". |
Yeah, stupid me. I should have seen that. LoL. |
For me, definitely one practical usage for this feature is possibility to use 2 browsers simultaneously. (It was not possible in Selenide before). I think that it's totally bad idea to use 2 browsers in test, but people ask for it too often. So, let's do it. |
Along with this feature, we have to also make an "object-oriented" alternative to Configuration class. There is one more thing to do about Configuration - make Configuration properties - static ones - like Configuration.timeout - ThreadLocal - the same as internal "automatic" driver in Selenide. Because currently you can have "driver per thread" in Selenide, but can't have "configuration per thread". But this seems to be filed as separate issue, like "make Configuration properties - ThreadLocal to allow custom configuration per thread in parallel testing" |
Unless we have proper implementation in Selenide, here is the simplest implementation which anybody can already use if needed: https://gist.github.com/yashaka/dc7607239518bd37298ef5eb5b08da9b |
Hi, |
Not yet. I plan to do it soon, but have not started yet.
…On Aug 15, 2017 10:14 AM, "Kiranannam" ***@***.***> wrote:
Hi,
Any update on this implementation?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#354 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARE3V_zAitPyJoz8kFgz2vIc-p1em9Uks5sYUVFgaJpZM4I_1T1>
.
|
@asolntsev, Thanks for your reply. Will wait for your update. |
@yashaka @jtolotta @Kiranannam FYI |
* SelenideDriver doesn't use Threads. It only contains WebDriver and SelenideProxy. * WebDriverContainer holds instances of SelenideDriver in ThreadLocal.
...to make opening a browser a "lazy" operation (see LazyEvaluationTest)
…river also use Driver class instead of Context (this is essentially the same)
it seems that having 2 separate classes only makes things harder
... to guarantee that it's not used inside Selenide code
... and move others to `statics` module
... and move others to `statics` module
Is it still impossible to have 2 web driver sessions in selenide ? |
@evgenyfedorenko Why? It's possible in several ways.
|
Awesome, thanks will check it out! |
Usually the "automatic driver management" is great.
But sometimes, when you need to operate with two opened browsers in one test - there is just no easy option in Selenide to do this.
Usecase:
Social network. Unfortunately there is no access to backend so you have to automate it as "full black box". You have to test "Joe can see a post created by his friend Bob".
In order to "save time" for "login/logout" the developer decides to open two browsers and login in each with different user - Joe and Bob correspondingly - so then once Bob created a post Joe can "immediately" check the result without "logout/login".
In Selenide there is the only option to implement this:
In one project we had to create our own "spikes" over Selenide WebDriverRunner implementation using reflection to get access to private fields in order to hide "driver substitution" and reduce boilerplate in tests...
It's sad:)
I recommend to refactor implementation of Selenide's driver management to be of object oriented style, where we have an object of Selenide wrapper over Selenium driver,
so we can create SelenideElement via:
or some other "naming" style can be chosen:
But the first style seems to me more "object oriented" and of "less magic" (find does not find, it creates a a lazy proxy element object which can find itself by request). We still can keep both aliases
find
andelement
, and even$
.Then we can build "procedural/static" helpers like$, $ $ on the base of the latter object-oriented implementation.
This will add a big plus to popularity of Selenide. Because many engineers are afraid of using Selenide because of its "the only procedural" nature (in context of "managing driver and creating elements").
The text was updated successfully, but these errors were encountered: