有没有办法从使用Selenium的POST请求开始?

时间:2011-04-14 09:16:44

标签: selenium

我正在尝试使用POST请求启动Selenium测试。

而不是简单的open(/startpoint)

我想做open(/startpoint, stuff=foo,stuff2=bar)

之类的事情

有没有办法做到这一点?

我问这个是因为发布到此起始点的原始页面取决于经常脱机的外部提供程序(开发环境),因此通常会过早失败(并且不是测试的主题)


我猜发送数据作为GET也会起作用。我更喜欢使用POST方法。

8 个答案:

答案 0 :(得分:31)

如果您正在使用Python selenium绑定,现在有selenium的扩展程序 - selenium-requests

  

扩展Selenium WebDriver类以包含请求函数   来自Requests库,同时完成所有需要的cookie和   请求标题处理。

示例:

from seleniumrequests import Firefox

webdriver = Firefox()
response = webdriver.request('POST', 'url here', data={"param1": "value1"})
print(response)

答案 1 :(得分:14)

简短回答:不。

但你可能会做一些事情。如果您打开一个测试页面(使用GET),然后评估该页面上的一些JavaScript,您应该能够复制POST请求。请参阅JavaScript post request like a form submit,了解如何在JavaScript中复制POST请求。

希望这有帮助。

答案 2 :(得分:7)

一个非常实用的方法是为您的测试创建一个虚拟起始页面,它只是一个带有POST的表单,它有一个“开始测试”按钮和一堆<input type="hidden" ...元素适当的职位数据。

例如,您可以创建包含以下内容的SeleniumTestStart.html页面:

<body>
  <form action="/index.php" method="post">
    <input id="starttestbutton" type="submit" value="starttest"/>
    <input type="hidden" name="stageid" value="stage-you-need-your-test-to-start-at"/>
  </form>
</body>

在此示例中,index.php是您的普通Web应用程序所在的位置。

测试开始时的Selenium代码将包括:

open /SeleniumTestStart.html
clickAndWait starttestbutton

这与自动化测试中使用的其他模拟和存根技术非常相似。您只是在嘲笑Web应用程序的入口点。

显然这种方法有一些限制:

  1. 数据不能太大(例如图像数据)
  2. 安全性可能是一个问题,因此您需要确保这些测试文件不会在生产服务器上结束
  3. 如果你需要在Selenium测试开始之前设置cookie,你可能需要使用像php而不是html这样的入口点
  4. 一些网络应用程序检查引荐来确保某人没有攻击应用程序 - 在这种情况下,这种方法可能无法工作 - 您可以在开发环境中放松此检查,以便它允许来自可信主机的引荐来源(不是自我,而是实际的测试主持人)
  5. 请考虑阅读我关于Qualities of an Ideal Test

    的文章

答案 3 :(得分:5)

Selenium IDE 允许您使用 storeEval 命令运行Javascript 。如果你有测试页面(HTML,而不是XML)并且你只需要执行POST请求,上面提到的解决方案就可以正常工作。

如果您需要进行 POST / PUT / DELETE 或任何其他请求,则需要采用其他方法:

<强>的XMLHttpRequest

下面列出的示例已经过测试 - 所有方法(POST / PUT / DELETE)都可以正常工作。

<!--variables-->
<tr>
    <td>store</td>
    <td>/your/target/script.php</td>
    <td>targetUrl</td>
</tr>
<tr>
    <td>store</td>
    <td>user=user1&amp;password</td>
    <td>requestParams</td>
</tr>
<tr>
    <td>store</td>
    <td>POST</td>
    <td>requestMethod</td>
</tr>
<!--scenario-->
<tr>
    <td>storeEval</td>
    <td>window.location.host</td>
    <td>host</td>
</tr>
<tr>
    <td>store</td>
    <td>http://${host}</td>
    <td>baseUrl</td>
</tr>
<tr>
    <td>store</td>
    <td>${baseUrl}${targetUrl}</td>
    <td>absoluteUrl</td>
</tr>
<tr>
    <td>store</td>
    <td>${absoluteUrl}?${requestParams}</td>
    <td>requestUrl</td>
</tr>
<tr>
    <td>storeEval</td>
    <td>var method=storedVars['requestMethod']; var url = storedVars['requestUrl']; loadXMLDoc(url, method); function loadXMLDoc(url, method) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4) { if(xmlhttp.status==200) { alert(&quot;Results = &quot; + xmlhttp.responseText);} else { alert(&quot;Error!&quot;+ xmlhttp.responseText); }}};&nbsp;&nbsp;xmlhttp.open(method,url,true); xmlhttp.send(); }</td>
    <td></td>
</tr>

澄清:

$ { requestParams } - 您要发布的参数(例如param1 = value1&amp; param2 = value3&amp; param1 = value3) 您可以根据需要指定任意数量的参数

$ { targetUrl } - 脚本的路径(如果您的页面位于http://domain.com/application/update.php,那么targetUrl应该等于/application/update.php)

$ { requestMethod } - 方法类型(在这种情况下,它应该是“POST”但可以是“PUT”或“DELETE”或任何其他方式)

答案 4 :(得分:4)

Selenium目前不提供API,但有几种方法可以在测试中启动HTTP请求。这取决于你所写的语言。

例如,在Java中,它可能如下所示:

// setup the request
String request = "startpoint?stuff1=foo&stuff2=bar";
URL url = new URL(request);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");

// get a response - maybe "success" or "true", XML or JSON etc.
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
StringBuffer response = new StringBuffer();
while ((line = bufferedReader.readLine()) != null) {
    response.append(line);
    response.append('\r');
}
bufferedReader.close();

// continue with test
if (response.toString().equals("expected response"){
    // do selenium
}

答案 5 :(得分:2)

嗯,我同意@Mishkin Berteig - 敏捷教练的回答。使用表单是使用POST功能的快捷方式。

无论如何,我看到一些关于javascript的提及,但没有代码。我有自己的需求,其中包括简单的POST和其他的jquery。

基本上,使用driver.execute_script()你可以发送任何javascript,包括Ajax查询。

#/usr/local/env/python
# -*- coding: utf8 -*-
# proxy is used to inspect data involved on the request without so much code.
# using a basic http written in python. u can found it there: http://voorloopnul.com/blog/a-python-proxy-in-less-than-100-lines-of-code/

import selenium
from selenium import webdriver
import requests
from selenium.webdriver.common.proxy import Proxy, ProxyType

jquery = open("jquery.min.js", "r").read()
#print jquery

proxy = Proxy()
proxy.proxy_type = ProxyType.MANUAL
proxy.http_proxy = "127.0.0.1:3128"
proxy.socks_proxy = "127.0.0.1:3128"
proxy.ssl_proxy = "127.0.0.1:3128"

capabilities = webdriver.DesiredCapabilities.PHANTOMJS
proxy.add_to_capabilities(capabilities)

driver = webdriver.PhantomJS(desired_capabilities=capabilities)

driver.get("http://httpbin.org")
driver.execute_script(jquery) # ensure we have jquery

ajax_query = '''
            $.post( "post", {
                "a" : "%s",
                "b" : "%s"
            });
            ''' % (1,2)

ajax_query = ajax_query.replace(" ", "").replace("\n", "")
print ajax_query

result = driver.execute_script("return " + ajax_query)
#print result

#print driver.page_source

driver.close()

# this retuns that from the proxy, and is OK
'''
POST http://httpbin.org/post HTTP/1.1
Accept: */*
Referer: http://httpbin.org/
Origin: http://httpbin.org
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.0.0 Safari/538.1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 7
Cookie: _ga=GAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; _gat=1
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Accept-Language: es-ES,en,*
Host: httpbin.org


None
a=1&b=2  <<---- that is OK, is the data contained into the POST
None
'''

答案 6 :(得分:1)

我使用BigDecimal将一个html表单注入页面,然后提交。它看起来像这样:

driver.execute_script()

如果您愿意,您可以将函数添加到 def post(path, params): driver.execute_script(""" function post(path, params, method='post') { const form = document.createElement('form'); form.method = method; form.action = path; for (const key in params) { if (params.hasOwnProperty(key)) { const hiddenField = document.createElement('input'); hiddenField.type = 'hidden'; hiddenField.name = key; hiddenField.value = params[key]; form.appendChild(hiddenField); } } document.body.appendChild(form); form.submit(); } post(arguments[1], arguments[0]); """, params, path) # example post(path='/submit', params={'name': 'joe'}) ,然后在您的代码中使用 \selenium\webdriver\chrome\webdriver.py

答案 7 :(得分:0)

from selenium import webdriver

driver = webdriver.Firefox()
driver.implicitly_wait(12)
driver.set_page_load_timeout(10)

def _post_selenium(self, url: str, data: dict):
    input_template = '{k} <input type="text" name="{k}" id="{k}" value="{v}"><BR>\n'
    inputs = ""
    if data:
        for k, v in data.items():
            inputs += input_template.format(k=k, v=v)
    html = f'<html><body>\n<form action="{url}" method="post" id="formid">\n{inputs}<input type="submit" id="inputbox">\n</form></body></html>'

    html_file = os.path.join(os.getcwd(), 'temp.html')
    with open(html_file, "w") as text_file:
        text_file.write(html)

    driver.get(f"file://{html_file}")
    driver.find_element_by_id('inputbox').click()

_post_selenium("post.to.my.site.url", {"field1": "val1"})

driver.close()