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

[java] implement DriverFinder completely independent of Service classes #11491

Merged
merged 11 commits into from Feb 27, 2023

Conversation

titusfortner
Copy link
Member

Description

This is an alternate implementation of #11411

Advantages:

  • better separation of concerns; it keeps the finding logic completely separate from Service classes
  • backwards compatible; user doesn't need to change anything in their code for this to work

Disadvantages:

  • The implementation defeats the purpose of the builder pattern; the value can be null in the constructor, and requires a setter/getter
  • Exceptions in finding the driver happen in Driver constructor, not the Service constructor

Motivation and Context

I got the idea from trying to see how I would implement this functionality in Ruby.

The underlying problem is that a user can create a service instance before the options instance. We can either:

  • Force the user to pass in options to the Service class if they are creating their own (Use Driver finder for sending Options to Selenium Manager #11411), but we agreed last TLC meeting that we didn't like that idea in general, so we want to deprecate that rather than extend it.
  • Somehow find and update the executable path on behalf of the user regardless of how they are constructing.

Is there a better Java pattern here? Like, I guess we can avoid the setter/getter by building a new Service instance from the Driver constructor with a builder method that takes an existing Service instance and the executable path from the DriverFinder, but that doesn't prevent a Service instance from having a null executable value when constructed, and errors still happen in driver constructor rather than the service construction.

Any feedback appreciated.

@codecov-commenter
Copy link

codecov-commenter commented Dec 27, 2022

Codecov Report

Base: 54.65% // Head: 54.65% // No change to project coverage 👍

Coverage data is based on head (0632c76) compared to base (728db91).
Patch has no changes to coverable lines.

❗ Current head 0632c76 differs from pull request most recent head 673cd7e. Consider uploading reports for the commit 673cd7e to get more accurate results

📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

Additional details and impacted files
@@           Coverage Diff           @@
##            trunk   #11491   +/-   ##
=======================================
  Coverage   54.65%   54.65%           
=======================================
  Files          85       85           
  Lines        5643     5643           
  Branches      244      244           
=======================================
  Hits         3084     3084           
  Misses       2315     2315           
  Partials      244      244           

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@pujagani
Copy link
Contributor

pujagani commented Jan 3, 2023

Can we not have a Require.nonNull check in the DriverService class constructors?

this calls the DriverService class constructor.
If executable is passed explicitly, it should not be null.

Since

public static ChromeDriverService createDefaultService() {
will use the DriverFinder methods to identify executable because user chooses to use the default mechanism.

Just a suggestion, I might be missing something here.

@titusfortner
Copy link
Member Author

can we not have a Require.nonNull check in the DriverService class constructors

Driver finder needs the options instance.
If service instance was always created in driver constructor, then we'd always have the options class for driver finder. But user can create it and pass it into the driver constructor, so we can't use finder. Service constructor needs to allow null executable because the builder is no longer locating the driver. It's getting set on an existing service instance in the driver constructor.
I don't see a good alternative that doesn't require the user to change code to initialize service class with options instance.

Copy link
Member

@diemol diemol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this PR looks better than #11411, thanks @titusfortner!

However, I agree with the comments, it'd be nice to have a single DriverFinder class.

@titusfortner titusfortner force-pushed the driver_finder2 branch 2 times, most recently from a59e870 to 2e91ebf Compare January 6, 2023 04:27
@titusfortner
Copy link
Member Author

So, this moves all the DriverFinder classes into one, except for SafariDriverFinder because the logic is different. We could probably get rid of that one too if we overloaded a couple methods in SafariDriver (2 valid service classes) and could push the logic for checking OS version etc to the Selenium Manager, but I'm not sure that's better.

Really, though, combining the builder pattern with the one-off setter/getter feels really weird to me. It's nice that it just works without the user needing to do anything, but I was hoping there might be a better way to do this... 😄

@titusfortner
Copy link
Member Author

Oh, and I changed the default error message to link to our documentation instead of directly to the driver URLs, which I think is preferable.

Copy link
Member

@diemol diemol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A small change requested to help code readability. Everything else looks 👍

Thank you!

@pujagani
Copy link
Contributor

pujagani commented Jan 6, 2023

Looks good to me overall.

@titusfortner
Copy link
Member Author

I'm moving this to draft because there is a selenium manager issue that needs to get resolved first, and it won't get released until at least 4.9

@titusfortner titusfortner mentioned this pull request Jan 7, 2023
@titusfortner
Copy link
Member Author

I figured out a simple way to remove the need for the SafariDriverFinder class by overloading DriverFinder's getPath()

@titusfortner
Copy link
Member Author

@diemol all the issues I ran into with the selenium manager binary have been sorted now.

@titusfortner titusfortner added this to the 4.9 milestone Jan 14, 2023
@titusfortner titusfortner force-pushed the driver_finder2 branch 2 times, most recently from a73b7d3 to 148cb95 Compare January 15, 2023 02:51
@pujagani
Copy link
Contributor

pujagani commented Feb 2, 2023

There seems to be a linting error in the GeckoDriverServiceTest. Can you please help fix it? Overall, the PR LGTM.

@titusfortner
Copy link
Member Author

Diego wanted me to keep the constants in the Service class; instead of calling the service class values from the driver, I created an interface and methods to get the values in the drivers.

Except, I can't get that class to load with Bazel. (please help)

Also, I updated the DriverInfo classes because isAvailable() will no longer error when just building the service class. To make that easier, I created a basic version for getting path from DriverFinder via SeleniumManager that ignores Options class.

@titusfortner titusfortner marked this pull request as ready for review February 21, 2023 22:54
@diemol
Copy link
Member

diemol commented Feb 22, 2023

I did not notice this PR being ready and I caused the conflict. I will review, solve the conflict, and if everything OK, I will merge it.

# Conflicts:
#	java/src/org/openqa/selenium/remote/service/DriverService.java
Copy link
Member

@diemol diemol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, @titusfortner!

CI failures are not related to this change.

@diemol diemol merged commit 1c70137 into SeleniumHQ:trunk Feb 27, 2023
@titusfortner titusfortner deleted the driver_finder2 branch June 23, 2023 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants