giorgiosironi / phpunit-selenium

Selenium RC integration for PHPUnit
http://www.phpunit.de/
Other
602 stars 271 forks source link

Missing interface of the actual selenium driver #394

Closed linaori closed 6 years ago

linaori commented 7 years ago

Right now I'm forced to use method calls resulting calling the __call() method in the selenium test case. This is really annoying and hard to abstract the driver. Can you add an interface we can use to call the methods on? I rather do something like $driver->getUrl() and $driver->setUrl(string $url) than $this->url() or $this->url(string $string).

I've tried extracting the interface in PhpStorm but it doesn't really work that well due to double signatures per method, nor am I planning on keeping this in sync.

The reason I'm asking this, is because I have written a small layer of abstraction using Page Objects, but I can't test this code because I can't mock __call.

https://github.com/giorgiosironi/phpunit-selenium/blob/master/PHPUnit/Extensions/Selenium2TestCase.php#L57-L96

giorgiosironi commented 7 years ago

The design decision there was to use __call() to minimize the amount of code to be added on the PHP side every time something is added to the Selenium JSON wire protocol. Autocompletion was still provided by @method annotations.

Speaking about the specific problem, mocking a class coming from an external library also has other problems: http://www.markhneedham.com/blog/2009/12/13/tdd-only-mock-types-you-own/ https://8thlight.com/blog/eric-smith/2011/10/27/thats-not-yours.html You should wrap the Selenium2TestCase class into a smaller interface you can control if you really want to test some code in isolation from it.

linaori commented 7 years ago

The problem here is that the TestCase also acts as the driver. I need the driver on its own, without it also being a test case, hence I want an interface that I can use. Sure I can wrap this class in my own interface, but if PhpStorm can't properly extract the method signatures, I won't bother, because it's too much to manually maintain.

So what I really want, is not having to use the TestCase class as driver, because this is where the problem starts.

The design decision there was to use __call() to minimize the amount of code to be added on the PHP side every time something is added to the Selenium JSON wire protocol

There hardly is a valid call for this kind of magic and using @method does not solve this problem.

http://www.markhneedham.com/blog/2009/12/13/tdd-only-mock-types-you-own/ https://8thlight.com/blog/eric-smith/2011/10/27/thats-not-yours.html

Yes and no. You can't properly unit-test without mocking those dependencies, however, I don't really care what happens if it's called, I just care that it's called, that's the behavior I want to test. If I have an interface, I can implement it for either a stub or make a prophecy out of it.

giorgiosironi commented 7 years ago

You can use the https://github.com/giorgiosironi/phpunit-selenium/blob/master/PHPUnit/Extensions/Selenium2TestCase/Driver.php class directly, passing instances of https://github.com/giorgiosironi/phpunit-selenium/blob/master/PHPUnit/Extensions/Selenium2TestCase/Command.php (subclasses) directly. However building these objects is not trivial as their URL on the API call to the Selenium Server needs to be composed. It's probably better to try to get a https://github.com/giorgiosironi/phpunit-selenium/blob/master/PHPUnit/Extensions/Selenium2TestCase/Session.php object and work from there, the TestCase delegates almost everything to it.

In general, this library is really tied to PHPUnit and difficult to reuse in isolation from it.

linaori commented 7 years ago

As I understood it, the Session object is the one actually calling the driver, but I was unable to access this object. Is this intentional or did I miss an option?

giorgiosironi commented 7 years ago

It's not exposed to test cases as they rely on the methods inherited from Selenium2TestCase (including __call()), but nothing stops you from creating your own object with https://github.com/giorgiosironi/phpunit-selenium/blob/master/PHPUnit/Extensions/Selenium2TestCase/SessionStrategy/Isolated.php#L59 if you need one.

linaori commented 7 years ago

Is there any documentation I can fall back on regarding this?

giorgiosironi commented 7 years ago

All classes other than Selenium2TestCase have always been taught as internal more than for reuse, so they have no accompanying documentation.