SeleniumHQ / selenium-google-code-issue-archive

Archive, please see main selenium repo
https://github.com/seleniumhq/selenium
345 stars 195 forks source link

WebDriver lacks HTTP response header and status code methods #141

Closed lukeis closed 8 years ago

lukeis commented 8 years ago

Originally reported on Google Code with ID 141


It would be useful to have methods to read the HTTP status code and headers from an
HTTP 
response.  HtmlUnit already has this functionality, but it's not been brought through
to WebDriver.

Reported by stephendv on 2009-02-01 16:05:44

lukeis commented 8 years ago
Issue 152 has been merged into this issue.

Reported by simon.m.stewart on 2009-09-14 17:42:11

lukeis commented 8 years ago
good feature

Reported by risticnemanja on 2009-10-16 13:27:22

lukeis commented 8 years ago
good feature

Reported by risticnemanja on 2009-10-16 13:27:31

lukeis commented 8 years ago
We will not be adding this feature to the WebDriver API as it falls outside of our current

scope (emulating user actions).

Reported by jmleyba on 2009-12-17 17:49:33

lukeis commented 8 years ago
This would make WebDriver unusable for testing.
Selenium is supporting this feature, so I guess I am stuck with selenium forever :)

Reported by ivanjanic on 2009-12-17 18:23:32

lukeis commented 8 years ago
Adding access for status code and response headers would be a really good addition.

If these features will not be added, then WebDriver cannot be regarded as a full web
testing tool, but merely a wrapper for various HTTP/S interaction APIs.

Reported by timo.westkamper on 2010-02-09 10:12:25

lukeis commented 8 years ago
"Emulating user actions" might be useful for a generic browser driver, but for a 
TESTING tool it will be necessary to read the status code, headers and cookie values.

This is needed for performing non-functional automated tests, e.g.:
- Does the logon form always result in a 302 redirect?
- Is the session cookie set before logon, or after (to identify session fixation attacks)?
- Is the page with my bank details cached or not?

Until these features are added, I too cannot use webdriver for testing.

Reported by stephendv on 2010-02-09 10:21:41

lukeis commented 8 years ago
I appreciate having a clean API, but this is honestly something that is very
important in a lot of my test cases so I hope it gets fixed.

Reported by ponzao on 2010-02-10 08:46:24

lukeis commented 8 years ago
yes agree with above commnets. For a web testing tool its is imperative to be able to
read HTTP headers.

Reported by pnakhat on 2010-03-05 09:16:04

lukeis commented 8 years ago
Issue 404 has been merged into this issue.

Reported by dawagner on 2010-03-05 11:41:07

lukeis commented 8 years ago
For the time being we are standing by our decision not to add this feature.  If we attempt
to make WebDriver the silver bullet of web testing, then it will suffer in overall
quality.

A few points to consider:

1. driver.get(url) blocks until the browser has loaded the page.  In the case of a
login redirect, what status/headers would you want returned?  By the semantics of the
API, we would 
return the response for the final loaded page.  You would end up with a 200 instead
of the 302 you're looking for.

2. WebDriver does support checking cookies, just not at the HTTP protocol level.  Take
a look at the WebDriver.Options interface:
http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/WebDriver.Options.html

3. If you want to test HTTP request/response headers, then write an appropriately sized
test and test those directly.  All you need is a simple HTTP client library (and as
you mentioned, 
HtmlUnit already offers some of these capabilities).  If you really want to combine
the two levels of testing, setup a proxy for your browsers so you can capture net traffic
and verify 
headers there.

Reported by ashley.leyba on 2010-03-10 12:41:45

lukeis commented 8 years ago
This means that the only reason is "it falls outside of our current scope (emulating
user actions)".

I find it a bit strange. Why doesn't this apply to managing cookies?

Additionally if in the "GettingStarted" Wiki page you write:
"WebDriver is a tool for automating testing web applications, and in particular to
verify that they work as expected". The possibility to access response code is very
useful for this purpose.

Reported by mguillemot@yahoo.fr on 2010-03-10 12:53:43

lukeis commented 8 years ago
In my case I'm trying to test that the last step in a flow, and that is supposed to
generate a PDF. I won't try to validate the contents, but I do need to check that the
page isn't an error. The PDF generation I can test at a different level.

Now, I could implement this with HtmlUnit or something, but that basically means that
my nicely reusable Page objects (which all use WebDriver) are worhthless. I'd be
re-implementing a lot of the steps that WebDriver already fixed for me in such a nice
way.

Hope you'll reconsider.

Reported by anders.r.sveen on 2010-03-17 12:59:22

lukeis commented 8 years ago
This feature is highly needed. When I call get() on a URL, I would like to know if the
correct page was loaded or if it was a 404. Currently I can only get page source and
look for the 404 string but it is highly dependent of underlying server (because I
don't have a custom 404 page in my webapp).

Reported by glaurung.aubrane on 2010-08-25 20:53:34

lukeis commented 8 years ago
Please reconsider this issue.  
@jmleyba/ashley :-)

In case #1 it is reasonable for Webdriver to not be very verbose with redirects, etc.
 I would expect to be able to see the HTTP headers / status code of the rendered page
that was returned by driver.get(url)

Testers frequently use tools like Firebug, HttpFox, Web Developer Toolbar (Firefox),
iehttpheaders (IE), the built in developer tools in Chrome, and Safari Web Inspector
to inspect headers from the browser.

I don't think that looking at headers of the rendered page is outside the scope of
a browser driver used as a testing tool.

Reported by colin.harrington on 2010-08-26 14:22:14

lukeis commented 8 years ago
I also find it crucial that WebDriver exposes the HTTP status code of the rendered page.
The same way you can get the raw, HTML by calling getPageSource() on the driver, or
getCurrentUrl(), you should be able to call getResponseCode(). How are the first two
methods so different to the last one here? 

If we apply your logic for not adding a method to get the HTTP status code, then you
also shouldn't add getPageSource(), since any data on the page should be extracted
from the DOM via the driver.

Reported by npellow on 2010-09-07 05:14:46

lukeis commented 8 years ago
This is a crucial feature amiss in the WebDriver API today and doing it with a light-weight
HTTP-only library doesn't cut it as what WebDriver does through its browser and HtmlUnit
integration is so much more than what happens at the HTTP level and thus impossible
(or at least, very, very hard) to replicate in a "lightweight" HTTP library.

For instance, when you submit a form, you would like to know if the resulting page
returns HTTP Status Code 400 because of bad content within the posted content or 200
if everything went okay. Testing this when the form itself relies on JavaScript that
might alter the form values before they are posted makes it virtually impossible to
test this in an HTTP-only library.

The reason we use WebDriver is be able to test the functionality as close to the user
experience as possible, and whether you want to admit it or not, HTTP status codes
are so close to the user experience that it makes no sense to hide them in the API.

Most users know what "404 Not Found" means and this is the response they get when browsing
to a page that doesn't exist in most cases. While the user doesn't look at the actual
HTTP status code, but an HTML representation of it, he is exposed to the status code
while WebDriver itself doesn't expose it to the test that is supposed to carry out
the same action as a regular user.

If you don't want to do anything complicated here, then please at least just expose
the Request and Reponse as strings so we can parse and make sense of it ourselves.
Hiding this information is limiting the ways WebDriver can be used, especially when
it's testing through HtmlUnit where everything happens programmatically anyway.

Reported by asbjornu on 2010-10-20 11:07:02

lukeis commented 8 years ago
This feature isn't going to happen. The recommended approach is to either extend the
HtmlUnitDriver to access the information you require or to make use of an external
proxy that exposes this information such as the BrowserMob Proxy (http://proxy.browsermob.com)

Reported by simon.m.stewart on 2010-10-20 11:37:49

lukeis commented 8 years ago
It's impossible to extend the HtmlUnitDriver when you're writing your tests in C#, since
there is no HtmlUnitDriver in C#. Or do you expect me to write a new "selenium-server-standalone-2.0a6.jar"
that exposes HTTP information and then write a new version of WebDriver that exposes
HTTP information to be able to get access to it?

If you enable people to get the source of the web page, you should enable people to
dig even further down into the protocol to detect whether the web application behaves
as it should or not. Just asserting on "visual" artifacts of a web page is simply just
not enough to get a full view of how your web application is behaving. It only tells
a part of the story and there's really no reason WebDriver can't tell the full story
(even though limited to how it would be seen through a web browser).

Reported by asbjornu on 2010-10-22 06:30:50

lukeis commented 8 years ago
Issue 919 has been merged into this issue.

Reported by dawagner on 2010-10-22 13:32:49

lukeis commented 8 years ago
WebDriver is concerned with driving the browser. Where more sophisticated information
is required it is designed to integrate effectively with other tools which can provide
this deeper level of information. In the case of inspecting HTTP traffic, the only
way to do this in a cross-browser way is via a proxy. WebDriver exposes APIs to make
it easy to set the proxy to use for a browser instance, so you can hook in whichever
is the most suitable tool for your project.

As a starting point, we recommend looking at the BrowserMob Proxy (http://proxy.browsermob.com
)

Reported by simonstewart@google.com on 2010-10-25 11:21:16

lukeis commented 8 years ago
Issue 950 has been merged into this issue.

Reported by dawagner on 2010-11-05 16:53:24

lukeis commented 8 years ago
How can I control browser locale without this? 

Reported by serge.shikov on 2010-12-16 12:43:17

lukeis commented 8 years ago
for testing mobile site is absolutely necessary for us to be able to pass headers with
user-agent and phone num.
I appreciate you don't want to pollute the api, but we need so we're going to write
it.
Is there a way to make it available to others as well as plugin or some more nice method
than a diff? 

Reported by uberto.gama on 2011-02-02 12:25:59

lukeis commented 8 years ago
The best way to contribute would be to contact Patrick Lightbody and see what can be
added to the BrowserMob Proxy. That's a project based on the proxy used by selenium,
but the focus there is on adding the functionality that projects, such as yours, require.

Reported by simon.m.stewart on 2011-02-02 13:30:08

lukeis commented 8 years ago
mmmh the point is we need headers control in writing our cucumber tests.
Writing stuff like
Given I'm a iphone user with msisidn "12345678"
etc.etc.

and we translate that using user-agent and msisdn headers.
From what I understood from their site BrowserMob has no integration with cucumber.
Of course the ideal setup would be for webdriver to drive the iphone browser itself,
but for the moment we're happy with fake user-agent. Currectly DevQA is using modify-headers
plugin to test them.

For the same reason we need to test also result codes and redirects, from inside cucumber
tests.

Reported by uberto.gama on 2011-02-02 14:23:04

lukeis commented 8 years ago
An issue tracker isn't really the right place for this conversation, but I understand
that the plan is to give the browsermob proxy an API.

Reported by simon.m.stewart on 2011-02-02 14:27:30

lukeis commented 8 years ago
Sad to see this issue marked as "Won't Fix", as it's an important one for me as the
others have noted above. An important part of our criteria for a web testing framework
is a test development environment that doesn't take too much knowhow, setup and maintenance
in and of itself. Since you're recommending an extension of HTMLUnitDriver, do you
have an example somewhere of how this is done?

Another criterion that's important for us is being able to keep our tests integrated.
If I can test a bunch of web app behavior in WebDriver but have to switch to BrowserMob
to check http responses, I apparently lose the ability to have a single test script.
Instead I have to split my test scripts, and fork my testing processes, based on what
WebDriver will and won't do. (It wouldn't be so bad splitting up testing based on meaningful
distinctions like functional vs. unit tests. But this would require splitting up at
a low level that runs across meaningful boundaries.) Wait, BrowserMob doesn't even
have an API? How then can it be recommended instead of WebDriver for use in automated
tests?

I can understand the desire to resist API bloat, but refusing to expose a widely requested
piece of information like this seems questionable.

Reported by huttarl on 2011-05-06 21:56:41

lukeis commented 8 years ago
Though this issue is marked as will not fix, can the experts provide samples on integrating
broowsermob or htmlunit with webdriver?

Reported by rparampa on 2011-05-19 01:29:24

lukeis commented 8 years ago
I second comment #31 -- are there any samples available for how we can work around this
deficiency in Selenium/WebDriver? It seems to be quite a common issue.

Reported by neuronexmachina on 2011-06-01 00:16:24

lukeis commented 8 years ago
I blogged about a workaround for this using an embedded proxy. 

See my HOWTO here: http://www.supermind.org/blog/968/howto-collect-webdriver-http-request-and-response-headers

Reported by superkelvint on 2011-06-22 16:53:26

lukeis commented 8 years ago
Issue 2047 has been merged into this issue.

Reported by dawagner on 2011-07-13 15:25:39

lukeis commented 8 years ago
In http://code.google.com/p/selenium/issues/detail?id=2047, dawagner suggests using
BrowserMob's proxy.

Three issues with that:
- it doesn't support header manipulation via the REST API
- it only supports java natively, so no use to us python programmers
- The WebDriver python bindings don't appear to support proxies, or if it does, it's
not obvious how.

Isn't this design choice negating one of the main benefits of using WebDriver over
the original Selenium, that of removing the need to run a separate server?

Reported by rwillmer on 2011-07-14 13:34:15

lukeis commented 8 years ago
We use the BrowserMob proxy as an example. You could use Fiddler, a commercial tool
or something you whip together yourself. Selenium is a browser automation framework,
not an HTTP recording framework, and as such HTTP recording and manipulation is out
of scope for the project.

In the common case, where you don't care about http headers, you can still run without
an additional server. In the case where that data is important to you, you will, almost
by definition, need a separate server.

Reported by simon.m.stewart on 2011-07-14 16:22:10

lukeis commented 8 years ago
Is it possible for you to give an example of how you configure the python bindings to
use a proxy?

Reported by rwillmer on 2011-07-14 16:24:34

lukeis commented 8 years ago
Is it also possible to use RemoteWebDriver with such a proxy? Local FirefoxDriver supports
it, but not a remote one.

Reported by neuronexmachina on 2011-07-14 17:09:50

lukeis commented 8 years ago
Re: "Selenium is a browser automation framework, not an HTTP recording framework"

The seleniumhq front page says "Selenium is a suite of tools to automate *web app testing*
across many platforms". The Google blog post introducing WebDriver (http://google-opensource.blogspot.com/2009/05/introducing-webdriver.html)
says it's "a ... framework for automated *testing of webapps*" [emphasis mine, in both].
Neither one mentions automating browsers. Web app testing is absent from your definition
at #36, yet core to why most people use Selenium and the promise of WebDriver.

Testing a web app, by definition, requires specifying (client-side) inputs and checking
(client-side) outputs of the web app. This often includes providing cookies as inputs,
and checking HTTP status of responses. If a web app is supposed to respond to a particular
URL with a particular status code and content type, but returns the wrong code or type,
the web app is malfunctioning, and one often needs to be able to test that. If a particular
interaction with a web app is supposed to show a certain icon in the upper right corner
of the screen, but instead displays a "broken icon" graphic, how do you test for that?
If we had access to response codes and content types we could probably do it by doing
a "get" on the image URL.

If WebDriver is limiting its scope to "browser automation" (actually certain restricted
features of browsers... browsers do have access to HTTP headers and response codes,
of course), at the expense of web app testing, you really ought to change your marketing,
which is misleading.

Reported by huttarl on 2011-07-14 18:57:52

lukeis commented 8 years ago
In your particular example, checking that an image resolves to a proper URL, I imagine
two API options we could employ:
1) Any page navigation you perform populates an array of all of the resources loaded,
and the full HTTP information about them.  This is a significant overhead that would
rarely be used, and is actually rather hard to do.
2) A way of querying the status code of any particular resource, along the lines of:
driver.getResponseForResourceAtUrl("http://foo")
or possibly
driver.getResponseForResource(webElement)

But if you're going to make that call, is that really any more convenient than calling
out to your favourite HTTP library, which will be part of the distribution of any language
you're using?

Reported by dawagner on 2011-07-14 23:23:19

lukeis commented 8 years ago
A simple GET of a static URL doesn't require Selenium, but I think his example includes
the response to a POST, cookie, or continuation ID.  It's not so simple to make a valid
test for that state.

Reported by jdbeutel on 2011-07-14 23:53:33

lukeis commented 8 years ago
All visible cookies can be trivially gotten in WebDriver, so a Cookies: header can be
trivially added to your request.

Ok, you have to write a five-line utility method, that's a bit annoying, but it's really
not that bad.

Reported by dawagner on 2011-07-15 08:28:51

lukeis commented 8 years ago
Note that for testing 404s we would appreciate being able to get the *current page status
code* (I know that this won't work for redirects - but we have 404 pages that are different
in dev and staging / production and writing a single test that covers both is a nuisance).

Reported by fuzzyman on 2011-07-26 23:15:05

lukeis commented 8 years ago
Btw, the often-suggested solution of using a proxy like BrowserMob's doesn't work with
RemoteWebDriver, since RemoteWebDriver apparently doesn't support setting a proxy.
See http://code.google.com/p/selenium/issues/detail?id=2051

Reported by neil%perfectmarket.com@gtempaccount.com on 2011-08-04 19:47:48

lukeis commented 8 years ago

Please reconsider a possibility to add custom headers to a request.

WebDriver is mentioned to emulate user behaviour?
In fact i can not emulate user behaviour on mobile devices, because those generally
use custom headers.

Reported by Dennis.Dedaj on 2011-09-08 07:22:29

lukeis commented 8 years ago
Issue 2462 has been merged into this issue.

Reported by dawagner on 2011-09-15 08:55:24

lukeis commented 8 years ago
But Issue 2462 has a viable solution which people can use NOW with selenium changing
their code base namely:

package org.openqa.selenium.htmlunit;

This fixes the issue - but I would perfer it to come back into HtmlUnitDriver

public class ExtendedHtmlUnitDriver extends HtmlUnitDriver
{
    public ExtendedHtmlUnitDriver(boolean enableJavascript)
    {
        super(enableJavascript);
    }

    public void setHeader(String name, String value)
    {
        this.getWebClient().addRequestHeader(name, value);
    }
}

Usage:
        ExtendedHtmlUnitDriver driver = new ExtendedHtmlUnitDriver(true);
        driver.setHeader("cac", "2200009990");

Reported by laptop.eadie on 2011-09-16 08:10:44

lukeis commented 8 years ago
We would like to see this feature implemented as well. 

In our current testing workflow we test if we see the right page and then test for
specific elements on the page. To make sure that we see the right page we check the
current url. But that's not enough because this site could be an error page. So we'd
like to test for the status code as well.

Reported by meike.wiemann on 2011-11-03 14:02:16

lukeis commented 8 years ago
Very interesting discussion. This is something that we needed as well. I think that
the API proposed by dawagner is a very elegant solution to this problem
   "driver.getResponseForResourceAtUrl("http://foo")"

In case anyone is interested, I implemented a similar Util method in Java using the
httpclient library that comes with the Selenium distribution

public static int sendGetRequest(String resourceUrl) {
    try {
        HttpClient client= new DefaultHttpClient();
        HttpGet get= new HttpGet(resourceUrl);
        HttpResponse response= client.execute(get);
        return response.getStatusLine().getStatusCode();        
    } catch (ClientProtocolException e) {
        logger.error("[sendGetRequest] Unexpected exception thrown", e);
    } catch (IOException e) {
        logger.error("[sendGetRequest] Unexpected exception thrown", e);
    }
    //if we get here there was an exception, return failure
    return HttpStatus.SC_METHOD_FAILURE;
}

public static boolean isResourceLoaded(String resourceUrl) {
    //get the image from the server
    int getStatusCode= Util.sendGetRequest(resourceUrl);
    //verify the image was retrieved successfully
    if(getStatusCode == HttpStatus.SC_OK)
        return true;
    else
        return false;
}

Reported by epombar on 2011-11-09 16:27:01

lukeis commented 8 years ago
I vote to reopen this issue (but it is hardly a defect)

Reported by lars.holmberg@redshirt.se on 2011-12-09 10:56:03

lukeis commented 8 years ago
Vote for reopening issue also. 
When you test web app you will need to check responses and requests.
IMHO looking for workarounds doesn't add points for using framework. 

Reported by vladyslav.shcherbanyuk@nzz.ch on 2011-12-27 14:25:32

lukeis commented 8 years ago
Vote for reopening as well. As it stands I will need to drop web driver and use htmlunit
directly, only because of a simle HTTP header.

Reported by b.bottema on 2012-01-04 15:11:56