【问题标题】:Making a POST request in Selenium without filling a form?在 Selenium 中发出 POST 请求而不填写表格?
【发布时间】:2025-12-29 14:20:13
【问题描述】:

我有一个应用程序 A 应该处理使用 POST 方法提交的表单。发起请求的实际表单位于完全独立的应用程序 B 中。我正在使用 Selenium 测试应用程序 A,我喜欢编写一个用于表单提交处理的测试用例。

如何做到这一点?这可以在 Selenium 中完成吗?应用程序 A 没有可以发起此请求的表单。

注意,请求必须使用 POST,否则我只能使用 WebDriver.get(url) 方法。

【问题讨论】:

  • 您为什么不用 selenium 填写表格并提交表格,并确保在执行完成时为您提供正确的数据。但是,如果应用程序 B 关闭,此测试将始终失败 - 换句话说,我认为您需要模拟此交互。
  • @Scott:我无法访问表单所在的应用程序 B。
  • 似乎唯一的方法是在您有权访问的应用程序中模拟表单,否则 selenium 在这种情况下没有最有意义。
  • 我认为表单模拟是最好的方法。您甚至可以使用 JavaScript 动态创建此表单

标签: forms testing post selenium request


【解决方案1】:

我认为使用 Selenium 是不可能的。没有办法使用 Web 浏览器无中生有地创建 POST 请求,而 Selenium 通过操纵 Web 浏览器来工作。我建议您改用 HTTP 库来发送 POST 请求,并与您的 Selenium 测试一起运行它。 (您使用什么语言/测试框架?)

【讨论】:

  • Java+JUnit。我可以使用其他工具发出 POST 请求,但如何让 Selenium 处理响应?
  • 除了直接访问本地文件系统外,使用浏览器你可以做几乎所有与网络相关的事情,包括以编程方式创建和提交 POST 有效负载
【解决方案2】:

使用 selenium,您可以执行任意 Javascript,包括 programmatically submit a form

使用 Selenium Java 执行最简单的 JS:

if (driver instanceof JavascriptExecutor) {
    System.out.println(((JavascriptExecutor) driver).executeScript("prompt('enter text...');"));
}

您可以使用 Javascript 创建 POST 请求,设置所需的参数和 HTTP 标头,然后提交。

// Javascript example of a POST request
var xhr = new XMLHttpRequest();
// false as 3rd argument will forces synchronous processing
xhr.open('POST', 'http://httpbin.org/post', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send('login=test&password=test');
alert(xhr.response);

在现代最前沿的浏览器中,您还可以使用fetch()

如果您需要将响应文本传递给 selenium,那么请使用 return this.responseTextreturn this.response 而不是 alert(this.responseText) 并将 execute_script(或 execute_async_script)的结果分配给变量(如果使用 python) .对于java,对应的executeScript()executeAsyncScript()

这是一个完整的python示例:

from selenium import webdriver

driver = webdriver.Chrome()

js = '''var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://httpbin.org/post', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

xhr.send('login=test&password=test');
return xhr.response;'''

result = driver.execute_script(js);

result 将包含您的 JavaScript 的返回值,前提是 js 代码是同步的。将false 设置为xhr.open(..) 的第三个参数会强制请求是同步的。将第三个参数设置为 true 或省略它会使请求异步。

❗️ 如果您正在调用 asynchronous js 代码,请确保使用 execute_script 而不是 execute_async_script,否则调用将不会返回任何内容!

注意:如果您需要将字符串参数传递给 javascript,请确保始终使用 json.dumps(myString) 转义它们,否则当字符串包含单引号或双引号或其他棘手字符时,您的 js 将中断。

【讨论】:

    【解决方案3】:

    我发现最简单的方法是制作一个中间页面,仅用于提交 POST 请求。让 selenium 打开页面,提交表单,然后获取最终页面的来源。

    from selenium import webdriver
    html='<html><head><title>test</title></head><body><form action="yoursite.com/postlocation" method="post" id="formid"><input type="hidden" name="firstName" id="firstName" value="Bob"><input type="hidden" name="lastName" id="lastName" value="Boberson"><input type="submit" id="inputbox"></form></body></html>'
    htmlfile='/tmp/temp.html'
        try:
            with open(htmlfile, "w") as text_file:
                text_file.write(html)
        except:
            print('Unable to create temporary HTML file')
    from selenium.webdriver.support.ui import WebDriverWait
    driver = webdriver.Firefox()
    driver.get('file://'+htmlfile)
    driver.find_element_by_id('inputbox').click();
    #wait for form to submit and finish loading page
    wait = WebDriverWait(driver, 30)
    response=driver.page_source
    

    【讨论】: