Skip to content
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

PageFactory.InitElements Does not work in Net Core as uses a deprecated dll from Net Framework #4387

Closed
Saetabis1 opened this issue Jul 30, 2017 · 13 comments

Comments

Projects
None yet
8 participants
@Saetabis1
Copy link

commented Jul 30, 2017

Meta -

OS: Windows 10 Pro
Selenium Version: 3.4.0
Browser: All

Expected Behavior -

PageFactory Init Elements

Actual Behavior -

Warning is raised:
System.TypeLoadException : Could not load type 'System.Runtime.Remoting.Proxies.RealProxy' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. at OpenQA.Selenium.Support.PageObjects.DefaultPageObjectMemberDecorator.CreateProxyObject(Type memberType, IElementLocator locator, IEnumerable1 bys, Boolean cache) at OpenQA.Selenium.Support.PageObjects.DefaultPageObjectMemberDecorator.Decorate(MemberInfo member, IElementLocator locator) at OpenQA.Selenium.Support.PageObjects.PageFactory.InitElements(Object page, IElementLocator locator, IPageObjectMemberDecorator decorator)
Error is raised
OneTimeSetUp: System.TypeLoadException : Could not load type 'System.Runtime.Remoting.Proxies.RealProxy' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c5 61934e089'.

Steps to reproduce -

Possible solution

Kind Regards,
Saetabis.

@p0deje p0deje added the C-dotnet label Jul 31, 2017

@matthewblott

This comment has been minimized.

Copy link

commented Oct 26, 2017

I suspected this had been deprecated. Thanks to @p0deje for logging this as I've been hunting for the correct library for the past 20 minutes!

@chrisgbaker

This comment has been minimized.

Copy link

commented Mar 5, 2018

Has there been any more thought to this issue?

@jimevans

This comment has been minimized.

Copy link
Member

commented Mar 5, 2018

PageFactory is being deprecated. Expect compiler warnings in the next release.

@Saetabis1

This comment has been minimized.

Copy link
Author

commented Mar 5, 2018

Thanks for the headsup @jimevans , I´ll close the issue if support will not be given. I know that maybe this is not the channel for the question, but there is planned a similar implementation of PageFactory in the future?

Again thanks for all your efforts on this project. Being using it for almost 3 years and is a great implementation. 😄

Kind regards,
Saetabis.

@jimevans

This comment has been minimized.

Copy link
Member

commented Mar 5, 2018

@Saetabis1 No. The implementation of PageFactory in .NET does not provide any real benefits in terms of code verbosity over other methods of defining page objects. To be clear, the pattern for deprecation will be as follows:

  • The PageFactory class will be marked with the Obsolete attribute
  • The code for the PageFactory and its supporting classes will be moved to another repo, maintaining source-level compatibility (no namespace/API changes)
  • Release artifacts will be generated from the new repository, and users will be encouraged to migrate to the new repository
  • The code will be removed from the Selenium repository

This will happen over several releases. The first step (deprecation warnings) will happen in the next release of Selenium. The "new repository" will have a big, honking message in the README that says, in effect, "This repository is not maintained, issues will not be fixed, PRs will not be accepted," because that will be true of the new repository. I will not be accepting PRs for that new repo, nor will I be maintaining the code with bug fixes. Consider this an invitation for someone in the community to take over maintenance of that part of the code, once it has been separated out into a new repository, and to feel free to innovate on it there.

@Saetabis1

This comment has been minimized.

Copy link
Author

commented Mar 5, 2018

Thanks for the detailed explanation.

Kind Regards,
Saetabis.

@Saetabis1 Saetabis1 closed this Mar 5, 2018

@AKrasheninnikov

This comment has been minimized.

Copy link

commented Mar 16, 2018

What should the consumer use instead?

@jimevans

This comment has been minimized.

Copy link
Member

commented Mar 16, 2018

@AKrasheninnikov The new organization is DotNetSeleniumTools, and the project is DotNetSeleniumExtras. The repository is here, and the first binary releases have been released via NuGet for both PageFactory and ExpectedConditions.

@AKrasheninnikov

This comment has been minimized.

Copy link

commented Mar 16, 2018

Thanks, In the simplest possible terms, it goes like this:

Install-Package DotNetSeleniumExtras.PageObjects -Version 3.11.0

then

using SeleniumExtras.PageObjects;
//using OpenQA.Selenium.Support.PageObjects;

@CurlyFire

This comment has been minimized.

Copy link

commented Mar 22, 2018

@jimevans What is the standard method of defining PageObjects in .Net instead of using the pagefactory ? You say there is no real benefit to using it.

Thanks!

@jimevans

This comment has been minimized.

Copy link
Member

commented Mar 22, 2018

@CurlyFire I'm not going to get into "standard methods" of defining Page Objects. That ventures in to "Best Practices" territory that often yields attempts at a one-size-fits-all solution that may not exist. Having said that, there's no functional difference between the following:

public class MyPage
{
    [FindsBy(How = How.Id, Using = "foo")]
    private IWebElement fooElement;

    public IWebElement FooElement
    {
        get { return this.fooElement; }
    }
}

and this:

public class MyPage
{
    public IWebElement FooElement
    {
        get { return this.driver.FindElement(By.Id, "foo")); }
    }
}

The two approaches are both lazily loaded, not attempting to find the element until the property is called; both yield the same level of encapsulation that the Page Object Pattern suggests to use; and both will work while adhering to most of the C# style guides that are out there. However, the latter is less verbose and doesn't require complex proxy objects that intercept method calls and act on them. Additionally, I've heard many, many requests over the years for users wanting to define locators in an external file, so they can be changed without recompilation. Though that, too, is of dubious value to me, the latter approach makes it possible; the former does not, as attribute data must be available at compile time. There may be stylistic differences that people don't care for[1], but to keep around a set of code that provides little benefit above stylistic preference that is also complex and difficult to maintain doesn't seem like the best use of the project's limited developer time and attention.

[1] Some "stylistic difference" examples: Don't like calling FindElement directly in the property accessor? Create a helper method on your base page class. Don't like not having the locators specified data-dictionary style at the top of the class? Use private By member variables to hold them. And so on.

@LirazShay

This comment has been minimized.

Copy link

commented Mar 29, 2018

@jimevans
Sorry, but your example absolutely conflicts with the PageObject pattern that says:

The public methods represent the services that the page offers

and

Try not to expose the internals of the page

So the real comparison between PageFactory and another lazy loading way should be:

    public class MyPage
    {
        private IWebDriver driver;

        [FindsBy(How = How.Id, Using = "foo")]
        private IWebElement fooElement;

        public MyPage DoBar()
        {
            fooElement.Click();
            return this;
        }
    }

and this:

    public class MyPage
    {
        private IWebDriver driver;

        private IWebElement fooElement
        {
            get
            {
                return driver.FindElement(By.Id("foo"));
            }
        }

        public MyPage DoBar()
        {
            fooElement.Click();
            return this;
        }
    }

In this example the original PageFactory example is less verbose.

@jimevans

This comment has been minimized.

Copy link
Member

commented Mar 29, 2018

@LirazShay Yes, you’re correct, that’s a far better approximation of a correct implementation of the Page Object Pattern, and completely at odds with most of the Page Object implementations that exist in the wild, in my experience. And that approach still requires a complex system of proxy objects that is difficult to maintain and understand. Further discussion on this issue will not change the decision on the removal of the .NET PageFactory implementation, so I’m going to make this the last word on the subject in this issue report.

@SeleniumHQ SeleniumHQ locked as resolved and limited conversation to collaborators Mar 29, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.