有没有办法使用Selenium启动POST请求?

wh6knrhe  于 2023-01-30  发布在  其他
关注(0)|答案(8)|浏览(173)

我正在尝试使用对应用程序的POST请求启动Selenium测试。
而不是简单的open(/startpoint)
我想执行类似open(/startpoint, stuff=foo,stuff2=bar)的操作
有什么办法可以做到吗?
我问这个问题是因为发布到这个起点的原始页面依赖于经常离线的外部提供者(开发环境),因此经常过早失败(并且不是测试的主题)
我想用GET发送数据也可以,我只是更喜欢使用POST方法。

bhmjp9jg

bhmjp9jg1#

如果你现在使用Python selenium绑定,那么selenium有一个扩展-selenium-requests
扩展SeleniumWebDriver类以包含Requests库中的请求函数,同时执行所有需要的cookie和请求头处理。
示例:

from seleniumrequests import Firefox

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

pcww981p2#

简短回答:没有。
但是你可以做一些过滤。如果你打开一个测试页面(用GET),然后在那个页面上评估一些JavaScript,你应该可以复制一个POST请求。参见JavaScript post request like a form submit,看看你如何在JavaScript中复制一个POST请求。
希望这个有用。

ukdjmx9f

ukdjmx9f3#

一种非常实用的方法是为测试创建一个虚拟的起始页,它只是一个POST表单,其中有一个“start test”按钮和一堆<input type="hidden"...元素,以及适当的POST数据。
例如,您可以创建一个包含以下内容的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.数据不能太大(例如图像数据)
1.安全性可能是一个问题,因此您需要确保这些测试文件不会最终出现在您的生产服务器上
1.如果您需要在Selenium测试开始之前设置cookie,那么您可能需要使用php之类的东西来创建入口点,而不是使用html
1.一些web应用检查引用者以确保没有人正在黑客攻击应用-在这种情况下,这种方法可能不起作用-您可以在开发环境中放松此检查,以便允许来自受信任主机的引用者(不是自己,而是实际的测试主机)
请考虑阅读我关于Qualities of an Ideal Test的文章

798qvoo8

798qvoo84#

我使用driver.execute_script()将一个html表单注入到页面中,然后提交它,如下所示:

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中,然后在代码中使用driver.post()

rseugnpd

rseugnpd5#

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

如果您需要发出POST/PUT/DELETE或任何其他请求,则需要另一种方法:

    • XML HTTP请求**!

下面列出的示例已经过测试-所有方法(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&param2 = value3&param1 = value3)您可以根据需要指定任意多个参数
${targetUrl}-脚本的路径(如果您的页面位于http://domain.com/application/update.php,则targetUrl应等于/application/update.php)
${requestMethod}-方法类型(在此特定情况下,它应该是"POST",但可以是"PUT"或"DELETE"或任何其他类型)

rmbxnbpk

rmbxnbpk6#

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
}
yjghlzjz

yjghlzjz7#

嗯,我同意@Mishkin Berteig - Agile Coach的回答。使用表单是使用POST特性的快速方法。
无论如何,我看到一些提到JavaScript,但没有代码。我有我自己的需要,其中包括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
'''
gzjq41n4

gzjq41n48#

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()

相关问题