web自动化(4)——POM设计重构

1. 什么是POM

Page Object Model 是ui自动化测试中常见的封装方式。

原理:将页面封装为PO对象,然后通过面向对象的方式实现UI自动化

2. 封装原则

  1. PO无需包含全部UI元素
  2. PO应当验证元素
  3. PO不应该包含断言
  4. PO不应该暴露元素

3. 怎么进行POM封装

面向对象:属性和方法

封装步骤:

  1. 创建类,代表页面
  2. 创建类的属性,代表页面中的元素
  3. 创建类的方法,代表页面中的交互动作

在项目新建文件user_po.py

from selenium.webdriver import Chromefrom selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait# 1.创建类
class IndexPage:"""首页:登录页面"""def __init__(self, driver: Chrome):  # 在进行实例化是被自动调用,可以接收参数self.driver = driver# 2.类的属性,即页面元素btn_login = (By.XPATH, '//*[@id="user_head_tip"]/a[1]')  # 立即登录按钮ipt_username = (By.XPATH, '//*[@id="login-email-address"]')  # 账号输入框ipt_password = (By.XPATH, '//*[@id="login-password"]')  # 密码输入框btn_submit = (By.XPATH, '//*[@id="ajax-login-submit"]')  # 登录按钮msg = (By.XPATH, '//*[starts-with(@id,"fanwe_")]/table/tbody/tr/td[2]/div[2]')  # 登录结果# 3.类的方法,即交互动作def login(self, username, password):self.driver.find_element(*self.btn_login).click()  # *表示元组解包self.driver.find_element(*self.ipt_username).send_keys(username)self.driver.find_element(*self.ipt_password).send_keys(password)self.driver.find_element(*self.btn_submit).click()# 显示等待:系统提示里不包含忘记密码并且系统系统不为空WebDriverWait(self.driver, 10).until(lambda x: "忘记密码?" not in self.driver.find_element(*self.msg).text and self.driver.find_element(*self.msg).text != "")msg = self.driver.find_element(*self.msg).textreturn msg# 1.一个页面一个类
class DealPage:"""交易页面:投资"""# 2.类的属性,即页面元素ipt_money = (By.XPATH, '//*[@id="J_BIDMONEY"]')  # 投资金额btn_tz_submit = (By.XPATH, '//*[@id="tz_link"]')  # 立即投资ipt_pay_password = (By.XPATH, '//*[@id="J_bid_password"]')  # 支付密码btn_pay_submit = (By.XPATH, '//*[@id="J_bindpassword_btn"]')  # 确定msg = (By.XPATH, '//*[@id="fanwe_success_box"]/table/tbody/tr/td[2]/div[2]')def __init__(self, driver: Chrome):  # 在进行实例化是被自动调用,可以接收参数self.driver = driver# 3.类的方法,即交互动作def pay(self, money, pay_password):self.driver.find_element(*self.ipt_money).send_keys(money)self.driver.find_element(*self.btn_tz_submit).click()self.driver.find_element(*self.ipt_pay_password).send_keys(pay_password)self.driver.find_element(*self.btn_pay_submit).click()msg = WebDriverWait(self.driver, 10).until(lambda x: self.driver.find_element(By.XPATH, '//*[@id="fanwe_success_box"]/table/tbody/tr/td[2]/div[2]').text)return msgif __name__ == '__main__':driver = Chrome()driver.implicitly_wait(10)  # 隐式等待driver.get('http://47.107.116.139/fangwei/index.php')page = IndexPage(driver)msg = page.login('admin', 'msjy123')print(msg)driver.get('http://47.107.116.139/fangwei/index.php?ctl=deal&id=25370&preview=1')page = DealPage(driver)msg = page.pay(100, 'msjy123')print(msg)driver.quit()

4. 引入pytest

  1. 自动判断用例执行结果
  2. 统计用例成功数量
  3. 统一形成测试报告

4.1 安装

pip install pytest

4.2 编写夹具fixture

测试用例所依赖的一些组件应该在夹具中设置就绪:例如启动浏览器,最大化浏览器等。在根目录创建conftest.py文件,在该文件中写夹具

import pytest
from selenium.webdriver import Chrome# scope用来指定夹具作用域,function指函数,module指模块,如果设置scope=function表示每执行一个函数都会进行浏览器重启和关闭
@pytest.fixture(scope='module')  # 这里设置scope=module是因为如果为函数级别的话,我们在test_user中第1个用例如果关闭了浏览器第二个用例就需要重新登录
def driver():driver = Chrome()driver.implicitly_wait(5)driver.maximize_window()yield driverdriver.quit()

创建test_user.py,代码如下:

from user_po import IndexPage, DealPage# 在用例中使用夹具:将夹具名称写在参数当中
def test_login(driver):driver.get('http://47.107.116.139/fangwei/index.php')page = IndexPage(driver)msg = page.login('admin', 'msjy123')assert msg == '成功登录'def test_deal(driver):driver.get('http://47.107.116.139/fangwei/index.php?ctl=deal&id=25370&preview=1')page = DealPage(driver)msg = page.pay(100, 'msjy123')assert msg == '投标成功!'

在pycharm终端输入pytest即可自动执行test_user.py中的两个测试用例。

4.3 编写测试用例

以登录功能为例,存在以下几种情况,不同的输入会有不同的输出结果,

  • 用户名密码为空:Email格式错误,请重新输入或者昵称格式错误,请重新输入
  • 用户名正确,密码为空:密码格式错误,请重新输入
  • 错误用户名,密码正确:用户不存在
  • 正确用户名,错误密码:密码错误
  • 正确用户名,正确密码:成功登录
  • 首先新建ddt_login.csv,用于存放我们的用例数据,做参数化使用
用户名,密码,登录结果
,,Email格式错误,请重新输入或者昵称格式错误,请重新输入
admin,,密码格式错误,请重新输入
asasasddd,msjy123,用户不存在
admin,msjy123456,密码错误
admin,msjy123,成功登录

接下来将我们的test_user.py代码修改一下,因为输入不再是固定的,所以使用参数传入:

import csvimport pytestfrom user_po import IndexPage, DealPage# 读取csv文件数据作为参数化数据,使用装饰器进行参数化
@pytest.mark.parametrize("data", csv.DictReader(open("ddt_login.csv", encoding="utf-8-sig")))
# 在用例中使用夹具:将夹具名称写在参数当中
def test_login(driver, data):driver.get('http://47.107.116.139/fangwei/index.php')page = IndexPage(driver)msg = page.login(data["用户名"], data["密码"])assert msg == data["登录结果"]def test_deal(driver):driver.get('http://47.107.116.139/fangwei/index.php?ctl=deal&id=25370&preview=1')page = DealPage(driver)msg = page.pay(100, 'msjy123')assert msg == '投标成功!'

5. po封装管理后台

要封装后台管理的po,如果新建po文件,如果每个po都新建一个文件会导致文件过多,因此我们需要将原来的user_po.py文件名修改为pages.py,然后在里面添加类就可以了。然后添加类的时候我们可以发现每个类都有一个init方法,造成了代码重复,因此我们使用BasePage抽象类,它表示所有页面共用的代码,我们将init方法写在BasePage类中,后续使用时只需要继承即可。修改后代码如下:

from selenium.webdriver import Chromefrom selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait# 抽象类,所有页面的公共代码,需要使用时继承即可
class BasePage:def __init__(self, driver: Chrome):  # 在进行实例化是被自动调用,可以接收参数self.driver = driver# 1.创建类
class IndexPage(BasePage):"""首页:登录页面"""# 2.类的属性,即页面元素btn_login = (By.XPATH, '//*[@id="user_head_tip"]/a[1]')  # 立即登录按钮ipt_username = (By.XPATH, '//*[@id="login-email-address"]')  # 账号输入框ipt_password = (By.XPATH, '//*[@id="login-password"]')  # 密码输入框btn_submit = (By.XPATH, '//*[@id="ajax-login-submit"]')  # 登录按钮msg = (By.XPATH, '//*[starts-with(@id,"fanwe_")]/table/tbody/tr/td[2]/div[2]')  # 登录结果# 3.类的方法,即交互动作def login(self, username, password):self.driver.find_element(*self.btn_login).click()  # *表示元组解包self.driver.find_element(*self.ipt_username).send_keys(username)self.driver.find_element(*self.ipt_password).send_keys(password)self.driver.find_element(*self.btn_submit).click()# 显示等待:系统提示里不包含忘记密码并且系统系统不为空WebDriverWait(self.driver, 10).until(lambda x: "忘记密码?" not in self.driver.find_element(*self.msg).text and self.driver.find_element(*self.msg).text != "")msg = self.driver.find_element(*self.msg).textreturn msg# 1.一个页面一个类
class DealPage(BasePage):"""交易页面:投资"""# 2.类的属性,即页面元素ipt_money = (By.XPATH, '//*[@id="J_BIDMONEY"]')  # 投资金额btn_tz_submit = (By.XPATH, '//*[@id="tz_link"]')  # 立即投资ipt_pay_password = (By.XPATH, '//*[@id="J_bid_password"]')  # 支付密码btn_pay_submit = (By.XPATH, '//*[@id="J_bindpassword_btn"]')  # 确定msg = (By.XPATH, '//*[@id="fanwe_success_box"]/table/tbody/tr/td[2]/div[2]')# 3.类的方法,即交互动作def pay(self, money, pay_password):self.driver.find_element(*self.ipt_money).send_keys(money)self.driver.find_element(*self.btn_tz_submit).click()self.driver.find_element(*self.ipt_pay_password).send_keys(pay_password)self.driver.find_element(*self.btn_pay_submit).click()msg = WebDriverWait(self.driver, 10).until(lambda x: self.driver.find_element(By.XPATH, '//*[@id="fanwe_success_box"]/table/tbody/tr/td[2]/div[2]').text)return msg

然后我们将之前写的admin.py中管理后台的代码进行po封装,同样是创建类,属性和方法,写入pages.py,如下:

import timefrom selenium.webdriver import Chromefrom selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWaitfrom funcs import img1code, is_login# 抽象类,所有页面的公共代码,需要使用时继承即可
class BasePage:def __init__(self, driver: Chrome):  # 在进行实例化是被自动调用,可以接收参数self.driver = driver# 1.创建类
class IndexPage(BasePage):"""首页:登录页面"""# 2.类的属性,即页面元素btn_login = (By.XPATH, '//*[@id="user_head_tip"]/a[1]')  # 立即登录按钮ipt_username = (By.XPATH, '//*[@id="login-email-address"]')  # 账号输入框ipt_password = (By.XPATH, '//*[@id="login-password"]')  # 密码输入框btn_submit = (By.XPATH, '//*[@id="ajax-login-submit"]')  # 登录按钮msg = (By.XPATH, '//*[starts-with(@id,"fanwe_")]/table/tbody/tr/td[2]/div[2]')  # 登录结果# 3.类的方法,即交互动作def login(self, username, password):self.driver.find_element(*self.btn_login).click()  # *表示元组解包self.driver.find_element(*self.ipt_username).send_keys(username)self.driver.find_element(*self.ipt_password).send_keys(password)self.driver.find_element(*self.btn_submit).click()# 显示等待:系统提示里不包含忘记密码并且系统系统不为空WebDriverWait(self.driver, 10).until(lambda x: "忘记密码?" not in self.driver.find_element(*self.msg).text and self.driver.find_element(*self.msg).text != "")msg = self.driver.find_element(*self.msg).textreturn msg# 1.一个页面一个类
class DealPage(BasePage):"""交易页面:投资"""# 2.类的属性,即页面元素ipt_money = (By.XPATH, '//*[@id="J_BIDMONEY"]')  # 投资金额btn_tz_submit = (By.XPATH, '//*[@id="tz_link"]')  # 立即投资ipt_pay_password = (By.XPATH, '//*[@id="J_bid_password"]')  # 支付密码btn_pay_submit = (By.XPATH, '//*[@id="J_bindpassword_btn"]')  # 确定msg = (By.XPATH, '//*[@id="fanwe_success_box"]/table/tbody/tr/td[2]/div[2]')# 3.类的方法,即交互动作def pay(self, money, pay_password):self.driver.find_element(*self.ipt_money).send_keys(money)self.driver.find_element(*self.btn_tz_submit).click()self.driver.find_element(*self.ipt_pay_password).send_keys(pay_password)self.driver.find_element(*self.btn_pay_submit).click()msg = WebDriverWait(self.driver, 10).until(lambda x: self.driver.find_element(By.XPATH, '//*[@id="fanwe_success_box"]/table/tbody/tr/td[2]/div[2]').text)return msgclass AdminLoginPage(BasePage):"""后台管理登录页面"""ipt_username = (By.XPATH, '/html/body/form/table/tbody/tr/td[3]/table/tbody/tr[2]/td[2]/input')ipt_password = (By.XPATH, '/html/body/form/table/tbody/tr/td[3]/table/tbody/tr[3]/td[2]/input')ipt_verify = (By.XPATH, '/html/body/form/table/tbody/tr/td[3]/table/tbody/tr[5]/td[2]/input')img_verify = (By.XPATH, '//*[@id="verify"]')btn_submit = (By.XPATH, '//*[@id="login_btn"]')def login(self, username, password):self.driver.find_element(*self.img_verify).screenshot("../temp/code.png")code = img1code("../temp/code.png")self.driver.find_element(*self.ipt_username).send_keys(username)self.driver.find_element(*self.ipt_password).send_keys(password)self.driver.find_element(*self.ipt_verify).send_keys(code)self.driver.find_element(*self.btn_submit).click()time.sleep(1)return is_login(self.driver)  # 使用is_login函数返回值作为交互返回值class AdminIndexPage(BasePage):"""后台管理首页"""ifm_top = (By.XPATH, '/html/frameset/frame[1]')ifm_left = (By.XPATH, '//*[@id="menu-frame"]')ifm_main = (By.XPATH, '//*[@id="main-frame"]')def to_deal(self):self.driver.refresh()# 进入框架iframe = self.driver.find_element(*self.ifm_top)self.driver.switch_to.frame(iframe)self.driver.find_element(By.LINK_TEXT, '贷款管理').click()  # 点击贷款管理self.driver.switch_to.default_content()  # 退出框架iframe = self.driver.find_element(*self.ifm_left)self.driver.switch_to.frame(iframe)self.driver.find_element(By.LINK_TEXT, '全部贷款').click()  # 点击全部贷款self.driver.switch_to.default_content()  # 退出框架iframe = self.driver.find_element(*self.ifm_main)self.driver.switch_to.frame(iframe)return AdminDealPage(self.driver)class AdminDealPage(BasePage):"""贷款管理页面"""btn_new_deal = (By.XPATH, '/html/body/div[2]/div[3]/input[1]')  # 新增贷款按钮tr_deal = (By.XPATH, '//tr[contains(@class,"row")]')  # 列表所有def new_deal(self):self.driver.find_element(*self.btn_new_deal).click()return AdminNewDealPage(self.driver)  # 返回po表示已经进入新增贷款页面class AdminNewDealPage(BasePage):"""新增贷款页面"""ipt_name = (By.XPATH, '/html/body/div[2]/form/table[1]/tbody/tr[4]/td[2]/input')  # 贷款名称ipt_shor_name = (By.XPATH, '/html/body/div[2]/form/table[1]/tbody/tr[5]/td[2]/input')  # 简短名称ipt_username = (By.XPATH, '/html/body/div[2]/form/table[1]/tbody/tr[6]/td[2]/input[1]')  # 会员名称btn_username = (By.XPATH, '//strong[text()="beifan"]')btn_city = (By.XPATH, '//*[@id="citys_box"]/div[1]/div[2]/input[1]')  # 所在城市sel_cate = (By.XPATH, '/html/body/div[2]/form/table[1]/tbody/tr[8]/td[2]/select')  # 分类-房产抵押btn_show_upload = (By.XPATH,'/html/body/div[2]/form/table[1]/tbody/tr[14]/td[2]/span/div[1]/div/div/button')  # 图片上传按钮btn_show_local_upload = (By.XPATH, '/html/body/div[6]/div[1]/div[2]/div/div[1]/ul/li[2]')  # 本地上传按钮ipt_upload = (By.XPATH, '//input[@type="file"]')  # 发送文件btn_submit_upload = (By.XPATH, '/html/body/div[6]/div[1]/div[3]/span[1]/input')  # 确定上传按钮sel_type = (By.XPATH, '/html/body/div[2]/form/table[1]/tbody/tr[15]/td[2]/select')  # 借款用途sel_contract = (By.XPATH, '/html/body/div[2]/form/table[1]/tbody/tr[17]/td[2]/select')  # 借款合同范本sel_tcontract = (By.XPATH, '/html/body/div[2]/form/table[1]/tbody/tr[18]/td[2]/select')  # 转让合同范本ipt_amount = (By.XPATH, '/html/body/div[2]/form/table[1]/tbody/tr[19]/td[2]/input')  # 借款金额ipt_rate = (By.XPATH, '/html/body/div[2]/form/table[1]/tbody/tr[27]/td[2]/input')  # 年利率ipt_enddate = (By.XPATH, '/html/body/div[2]/form/table[1]/tbody/tr[28]/td[2]/input')  # 筹标期限btn_status = (By.XPATH, '/html/body/div[2]/form/table[1]/tbody/tr[33]/td[2]/label[1]/input')  # 借款状态ipt_start_time = (By.XPATH, '//*[@id="start_time"]')  # 开始时间btn_submit = (By.XPATH, '/html/body/div[2]/form/table[6]/tbody/tr[2]/td[2]/input[4]')  # 新增提交按钮msg=(By.XPATH, '/html/body/div/table/tbody/tr[3]/td')def submit(self, data):  # data是包含了多个参数的字典"""提交新的贷款"""# 贷款名称self.driver.find_element(*self.ipt_name).send_keys(data['name'])# 简短名称self.driver.find_element(*self.ipt_shor_name).send_keys(data['shor_name'])# 会员名称self.driver.find_element(*self.ipt_username).send_keys(data['username'])self.driver.find_element(*self.btn_username).click()# 城市self.driver.find_element(*self.btn_city).click()# 分类-房产抵押el = self.driver.find_element(*self.sel_cate)Select(el).select_by_visible_text(data['cate'])# 图片上传self.driver.find_element(*self.btn_show_upload).click()self.driver.find_element(*self.btn_show_local_upload).click()self.driver.find_element(*self.ipt_upload).send_keys(data['upload'])self.driver.find_element(*self.btn_submit_upload).click()# 借款用途el = self.driver.find_element(*self.sel_type)Select(el).select_by_visible_text(data['type'])# 借款合同范本el = self.driver.find_element(*self.sel_contract)Select(el).select_by_visible_text(data['contract'])# 转让合同el = self.driver.find_element(*self.sel_tcontract)Select(el).select_by_visible_text(data['tcontract'])# 借款金额el = self.driver.find_element(*self.ipt_amount)el.clear()el.send_keys(data['amount'])# 年利率el = self.driver.find_element(*self.ipt_rate)el.clear()el.send_keys(data['rate'])# 筹标期限el = self.driver.find_element(*self.ipt_enddate)el.clear()el.send_keys(data['enddate'])# 借款状态self.driver.find_element(*self.btn_status).click()# 开始时间el = self.driver.find_element(*self.ipt_start_time)self.driver.execute_script("arguments[0].scrollIntoView()", el)self.driver.execute_script(f"arguments[0].value='{data['start_time']}'", el)# 新增提交self.driver.find_element(*self.btn_submit).click()# 系统提示el = self.driver.find_element(*self.msg)return el.text

完成后我们创建test_admin.py文件,去编写测试用例,我们在编写新增贷款流程的测试用例的时候,首先需要登录,我们可以在conftest.py中新建一个fixture夹具,如下:

import pytest
from selenium.webdriver import Chromefrom funcs import save_cookies, load_cookies,is_login
from pages import AdminLoginPage# scope用来指定夹具作用域,function指函数,module指模块,如果设置scope=function表示每执行一个函数都会进行浏览器重启和关闭
@pytest.fixture(scope='module')  # 这里设置scope=module是因为如果为函数级别的话,我们在test_user中第1个用例如果关闭了浏览器第二个用例就需要重新登录
def driver():driver = Chrome()driver.implicitly_wait(5)driver.maximize_window()yield driverdriver.quit()@pytest.fixture(scope='session')
def admin_driver():"""已经登陆的浏览器,给test_admin使用"""driver = Chrome()driver.implicitly_wait(5)driver.maximize_window()load_cookies(driver)# 判断:只有未登录才进行登录流程if is_login(driver) is False:page = AdminLoginPage(driver)  # 实例化assert page.login('admin', 'msjy123') is Trueyield driversave_cookies(driver)driver.quit()

这样我们在test_admin.py中就可以使用admin_driver

from pages import *def test_new_deal(admin_driver):"""已经登录成功状态"""page = AdminIndexPage(admin_driver)page = page.to_deal()  # 跳转到贷款管理page = page.new_deal()  # 跳转到新增贷款# data表示输入的数据data = {'name': '借款1亿买别墅','shor_name': '买别墅','username': 'beifan','cate': '|--房产抵押标','upload': r'D:\pythonProject2\code.png','type': '个人消费','contract': '等额本息合同范本【担保】','tcontract': '付息还本合同范本【普通】','amount': '100000000','rate': '5','enddate': '30','start_time': '2023-12-25 18:02:02'}msg = page.submit(data)assert msg == '添加成功'

也可以在test_admin.py中继续添加测试用例,测试不同的输入数据和结果。这里不再举例。最后在终端运行可以看到测试通过,也可以创建main.py进行运行

import pytestif __name__ == '__main__':pytest.main()

写到这里POM封装就基本完成了,整理下项目目录,如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/583333.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

架构设计系列 5:常见架构介绍

前面讲了架构是什么,架构的发展史,架构设计的基础理论,这次针对常见架构设计风格进行介绍和分析。 一、MVC:三层架构经典 经典的 MVC 架构(Model-View-Controller)架构是软件系统架构设计中的经典&#xf…

数据结构与算法教程,数据结构C语言版教程!(第二部分、线性表详解:数据结构线性表10分钟入门)一

第二部分、线性表详解:数据结构线性表10分钟入门 线性表,数据结构中最简单的一种存储结构,专门用于存储逻辑关系为"一对一"的数据。 线性表,基于数据在实际物理空间中的存储状态,又可细分为顺序表&#xff…

NFC物联网构建移动智能仓储系统解决方案

仓储管理作为企业研发生产活动的重要环节,正朝着标准化、信息化方向发展。高新作为典型的资产密集 技术密集型企业,原料样品为代表的资产数量巨大品种繁杂,对仓库管理的实时性及准确性要求较高。传统的人工作业模式和管理方法逐渐难以满足仓储管理对高效…

【 YOLOv5】目标检测 YOLOv5 开源代码项目调试与讲解实战(4)-自制数据集及训练(使用makesense标注数据集)

如何制作和训练自己的数据集 看yolov5官网创建数据集1.搜索需要的图片2.创建标签标注数据集地址:放入图片后选择目标检测创建文档,每个标签写在单独的一行上传结果此处可以编辑类别把车框选选择类别即可导出数据 3.新建一个目录放数据写yaml文件 4. 测试…

【赠书第14期】AI短视频制作一本通:文本生成视频+图片生成视频+视频生成视频

文章目录 前言 1 前期准备 2 拍摄与录制 3 后期编辑 4 技巧与注意事项 5 推荐图书 6 粉丝福利 前言 随着智能技术的迅猛发展,AI 短视频制作成为了一种新兴而创新的表达方式,广泛应用于社交媒体、广告营销、教育培训等领域。本文将介绍 AI 短视频…

JavaScript介绍,特点及组成(详解)

✨前言✨   本章将介绍 JavaScript 的基本概念、编写方法,并带领大家编写第一个 avaScript 程序。 🍒欢迎点赞 👍 收藏 ⭐留言评论 📝私信必回哟😁 🍒博主将持续更新学习记录收获,友友们有任何…

垃圾收集器与内存分配策略

内存分配和回收原则 对象优先在Eden区分配 大对象直接进入老年代 长期存活的对象进入老年代 什么是内存泄漏 不再使用的对象在系统中未被回收,内存泄漏的积累可能会导致内存溢出 自动垃圾回收与手动垃圾回收 自动垃圾回收:由虚拟机来自动回收对象…

什么是高并发系统?

1.1 什么是高并发? 高并发(High Concurrency),通常是指通过设计保证系统能够同时处理很多请求。即在同一个时间点,有很多的请求同时访问同一个接口。高并发意味着大流量,需要运用技术手段去抵抗这种大流量…

用通俗易懂的方式讲解大模型:Prompt 提示词在开发中的使用

OpenAI 的 ChatGPT 是一种领先的人工智能模型,它以其出色的语言理解和生成能力,为我们提供了一种全新的与机器交流的方式。但不是每个问题都可以得到令人满意的答案,如果想得到你所要的回答就要构建好你的提示词 Prompt。本文将探讨 Prompt 提…

yolov5旋转目标检测-遥感图像检测-无人机旋转目标检测-附代码和原理

综述 为了解决旋转目标检测问题,研究者们提出了多种方法和算法。以下是一些常见的旋转目标检测方法: 基于滑动窗口的方法:在图像上以不同的尺度和角度滑动窗口,通过分类器判断窗口中是否存在目标。这种方法简单直观,…

Flutter 三点二:Dart 异步 async 和 await

async 和 await Future 链式调用 更清晰异步操作依赖关系比较复杂 可使用async awaitasync await 调用逻辑更清晰async await 异常处理 try{}catch(){} 即可async 修饰的方法 总是返回Future对象 不会阻塞主线程await 关键字只有在async修饰的方法内才有效都是把事件交给 Even…

数据可视化能为我们带来哪些好处?

在信息爆炸的时代,数据量呈指数级增长,企业和个人都面临着处理大量信息的挑战。在这个背景下,数据可视化崭露头角,成为解决复杂数据呈现和理解难题的得力工具。那么,数据可视化究竟能为我们带来哪些好处呢?…

SeaTunnel流处理同步MySQL数据至ClickHouse

ClickHouse是一种OLAP类型的列式数据库管理系统,ClickHouse完美的实现了OLAP和列式数据库的优势,因此在大数据量的分析处理应用中ClickHouse表现很优秀。 SeaTunnel是一个分布式、高性能、易扩展、用于海量数据同步和转化的数据集成平台。用户只需要配置…

YOLOv5改进 | 2023注意力篇 | BiFormer双层路由注意力机制(Bi-level Routing Attention)

一、本文介绍 BiFormer是一种结合了Bi-level Routing Attention的视觉Transformer模型,BiFormer模型的核心思想是引入了双层路由注意力机制。在BiFormer中,每个图像块都与一个位置路由器相关联。这些位置路由器根据特定的规则将图像块分配给上层和下层路…

网站提示“不安全”怎么解决

在互联网中,安全问题至关重要。访问某些网站时,可能会遇到“不安全”警告,通常是由于缺乏SSL证书。SSL证书是数字证书,用于确保互联网通信的安全和保密。 “不安全”问题通常源于缺少SSL证书。SSL通过加密通信,防止第三…

mac下jd-gui提示没有找到合适的jdk版本

mac下jd-gui提示jdk有问题 背景解决看一下是不是真有问题了方法一:修改启动脚本方法二:设置launchd环境变量 扩展动态切jdk脚本(.bash_profile) 背景 配置了动态jdk后,再次使用JD-GUI提示没有找到合适的jdk版本。 解决 看一下是不是真有问题…

学习使用wps将ppt的页面保存为图片的方法

学习使用wps将ppt的页面保存为图片的方法 方案 方案 1、打开ppt,点击文件,另存为,选择文件类型为图片格式,jpg或者png,如下图: 2、点击每张幻灯片

MacOS安装JDK8

下载 oracle官网下载。 oracle官网 镜像下载。 华为:https://repo.huaweicloud.com/java/injdk:https://www.injdk.cn 安装 下载完成后双击pkg,按提示流程安装。 安装完成后打开终端窗口,执行命令查看版本: java -…

MySql 性能优化神器之 explain 详解

目录 一. 前言 二. explain 详解 2.1. 概念 2.2. 数据准备 2.3. id 2.3.1. id 相同,执行顺序由上至下 2.3.2. id 不同,数字越大优先级越高 2.3.3. id 存在相同的和不同的 2.4. select_type 2.5. table 2.6. partitions 2.7. type 2.7.1. sy…

【Python基础】字符串

文章目录 [toc]什么是字符串索引示例索引越界 切片语法示例 字符串方法find()方法rfind()方法count()方法replace()方法 个人主页:丷从心 系列专栏:Python基础 什么是字符串 如下定义的变量url存储的是字符串类型的值 url www.baidu.com print(url)u…