当前位置: 首页 > news >正文

UI自动化测试示例:python+pytest+selenium+allure

重点应用是封装、参数化:

比如在lib文件夹下,要存储封装好的方法和必要的环境变量(指网址等)

1.cfg.py:封装网址和对应的页面

SMP_ADDRESS = 'http://127.0.0.1:8234'SMP_URL_LOGIN        = f'{SMP_ADDRESS}/login.html'
SMP_URL_DEVICE_MODEL = f'{SMP_ADDRESS}/index.html#/devicemodel'
SMP_URL_SERVICE_RULE = f'{SMP_ADDRESS}/index.html#/svcrule'

二、登录部分 

2.1 lib.py-登录模块的封装

主要就是输入账号名和密码进行测试。 

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
import time
from lib.cfg import *class SMP_UI:def __init__(self):options = webdriver.ChromeOptions()#排除一些不需要的日志输出。options.add_experimental_option( 'excludeSwitches', ['enable-logging'])self.wd = webdriver.Chrome(options=options)self.wd.implicitly_wait(3) #隐式等待时间为5秒,等待元素加载完成#登录模块测试def login(self, username, password):self.wd.get(SMP_URL_LOGIN) #打开登录网址#time.sleep(1)#sleep方便观察if username is not None:self.wd.find_element(By.ID, 'username').send_keys(username)if password is not None:self.wd.find_element(By.ID, 'password').send_keys(password)self.wd.find_element(By.ID, 'loginBtn').click()#点击登录按钮smpUI = SMP_UI()

2.2自动化测试脚本代码-登录

from selenium.webdriver.common.by import By
import time,pytest
from lib.webUI_smp import smpUIdef test_SMP_login_001():#正确账号和密码smpUI.login('byhy','sdfsdf' )nav = smpUI.wd.find_elements(By.TAG_NAME, 'nav') #登陆后就可以查看nav了,有信息代表登陆成功assert nav != []@pytest.fixture
def clearAlert():yieldtry:smpUI.wd.switch_to.alert.accept()except Exception as e:print(e)@pytest.mark.parametrize('username, password, expectedalert', [(None, 'sdfsdf', '请输入用户名'),#空用户名('byhy', None, '请输入密码'),#空密码('byhy', 'sdfsd',   '登录失败: 用户名或者密码错误'),#少输入密码('byhy', 'sdfsdff', '登录失败: 用户名或者密码错误'),#多输入密码('byh', 'sdfsdf',   '登录失败: 用户名不存在'),#少输入用户名('byhyy', 'sdfsdf', '登录失败: 用户名不存在'),#多输入用户名])
def test_SMP_login_002(username, password, expectedalert, clearAlert):smpUI.login(username, password)smpUI.wd.implicitly_wait(5)#隐式等待alert = smpUI.wd.switch_to.alert.textassert alert == expectedalert #对弹出框进行断言对比

三、商品部分

3.1 lib.py-商品服务模块的封装

主要就是添加商品、删除商品等,输出第一页的第一条的值(检查返回值) 

    #添加设备模块检测def add_device_model(self, devType, name, desc):# 实例化选择框做为对象select = Select(smpUI.wd.find_element(By.ID, "device-type"))# 选择对应列表中的种类select.select_by_visible_text(devType)#清除填充框后填-设备型号ele = smpUI.wd.find_element(By.ID, 'device-model')ele.clear()ele.send_keys(name)#清除填充框后填-型号描述ele = smpUI.wd.find_element(By.ID, 'device-model-desc')ele.clear()ele.send_keys(desc)#点提交smpUI.wd.find_element(By.CSS_SELECTOR, '.add-one-submit-btn-div .btn').click()# time.sleep(1)#得到第一页的设备信息(注:一页五条),是显示第一页的第一个数据def get_first_page_device_models(self):time.sleep(1)self.wd.implicitly_wait(0)values = self.wd.find_elements(By.CSS_SELECTOR,'.field-value')self.wd.implicitly_wait(10)deviceModels = []for idx, value in enumerate(values):if (idx+1) % 3 == 0:deviceModels.append([values[idx-2].text, values[idx-1].text, values[idx].text])return deviceModels#删除第一个项目def del_first_item(self) -> bool:self.wd.implicitly_wait(0)delBtn = self.wd.find_elements(By.CSS_SELECTOR,'.result-list-item:first-child .result-list-item-btn-bar span:first-child')self.wd.implicitly_wait(10)if not delBtn:return FalsedelBtn[0].click()self.wd.switch_to.alert.accept()return True

3.2自动化测试脚本代码-商品服务

之间登录商品增删改查的界面。注意编完数据后要删除

from selenium.webdriver.common.by import By
import time,pytest
from lib.webUI_smp import smpUI
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from lib.cfg import *@pytest.fixture(scope='module')
def inDeviceModelMgr():print('inDeviceModelMgr setup')smpUI.login('byhy','sdfsdf' ) #直接登录smpUI.wd.get(SMP_URL_DEVICE_MODEL)#登录后转到SMP_URL_DEVICE_MODEL这个主界面yield@pytest.fixture()
def delAddedDeviceModel():yieldprint('删除添加的设备型号')smpUI.del_first_item()@pytest.mark.parametrize('type, device, desc', [("存储柜", 'hebut-cn-box-01', '河北工业大学菜鸟柜子01柜-10大20中40小'),#添加设备-存储柜测试("存储柜", '河'*100, '河北工业大学菜鸟柜子02柜-10大20中40小'),#测试名称最大长度
("电瓶车充电站", 'hebut-dpccdz-es-01', '河北工业大学北辰充电站01站-220v电瓶车充电站'),#添加设备-电瓶车充电站
("洗车站", 'hebut-xcz-washcar-01', '河北工业大学洗车站东站'),#添加设备-洗车站测试
("汽车充电站", 'hebut-powercar-01', '河北工业大学7千瓦汽车充电站01'),#添加设备-汽车充电站])
#添加设备-存储柜测试
def test_SMP_device_model_001(type,device,desc,inDeviceModelMgr, delAddedDeviceModel):# 点击添加按钮topBtn = smpUI.wd.find_element(By.CSS_SELECTOR, '.add-one-area > span')if topBtn.text == '添加':topBtn.click()smpUI.add_device_model(type,device,desc)dms = smpUI.get_first_page_device_models()assert  dms == [[type,device,desc    ]]smpUI.wd.implicitly_wait(3)def test_SMP_device_model_501(inDeviceModelMgr, delAddedDeviceModel):# 点击添加按钮topBtn = smpUI.wd.find_element(By.CSS_SELECTOR, '.add-one-area > span')if topBtn.text == '添加':topBtn.click()smpUI.add_device_model("存储柜", 'daixiugai-01', '待修改测试数据-01')smpUI.wd.implicitly_wait(3)# 点击修改按钮changeBtn = smpUI.wd.find_element(By.XPATH,'/html/body/main/div[3]/div/div[2]/span[2]').click()# if changeBtn.text == '修改':#     changeBtn.click()# 实例化选择框做为对象select = Select(smpUI.wd.find_element(By.XPATH,'/html/body/main/div[3]/div/div[1]/div[1]/select'))# 选择对应列表中的种类select.select_by_visible_text("洗车站")# 清除填充框后填-设备型号ele = smpUI.wd.find_element(By.XPATH,'/html/body/main/div[3]/div/div[1]/div[2]/input')ele.clear()ele.send_keys('修改后的型号1')# 清除填充框后填-型号描述ele = smpUI.wd.find_element(By.XPATH,'/html/body/main/div[3]/div/div[1]/div[3]/input')ele.clear()ele.send_keys('修改后的型号描述')# 点提交smpUI.wd.find_element(By.XPATH,'/html/body/main/div[3]/div/div[2]/span[1]').click()dms = smpUI.get_first_page_device_models()assert  dms == [["洗车站",'修改后的型号1','修改后的型号描述' ]]smpUI.wd.implicitly_wait(3)def test_SMP_device_model_601(inDeviceModelMgr, delAddedDeviceModel):# 点击添加按钮topBtn = smpUI.wd.find_element(By.CSS_SELECTOR, '.add-one-area > span')if topBtn.text == '添加':topBtn.click()smpUI.add_device_model("存储柜", 'daixshanchu-01', '待删除测试数据-01')time.sleep(1)smpUI.del_first_item()dms = smpUI.get_first_page_device_models()assert ['存储柜', 'daixshanchu-01', '待删除测试数据-01'] not in dmssmpUI.wd.implicitly_wait(3)

四、业务规则部分

4.1 lib.py-业务规则模块的封装

    def add_svc_rule(self, ruleName:str, ruleType:str,minFee:str,estFee:str, feeRate=None, desc:str=None):"""添加业务规则:param ruleName: 规则名称:param ruleType: 规则类型,只能是:后付费-上报业务量、预付费-下发费用、预付费-下发业务量:param minFee: 最小费用,不需要时,填写空字符串:param estFee: 预计费用,不需要时,填写空字符串:param desc: 描述:param feeRate: 费率, 如果ruleType是预付费-下发费用: 不用填写预付费-下发业务量: 格式为 ['千瓦时', '1'], 元素分别是 单位、单价后付费-上报业务量: 格式为 [['10L', '小时','1'],['20L', '小时','2'],], 每个元素里面分别是 : 业务码、单位、单价:return:"""#名称输入ele = self.wd.find_element(By.CSS_SELECTOR, '.add-one-form > .field:nth-child(1) >input')ele.clear()ele.send_keys(ruleName)select = Select(self.wd.find_element(By.CSS_SELECTOR, ".add-one-form select"))select.select_by_visible_text(ruleType)if ruleType != '后付费-上报业务量': #预付费-下发业务量操作ele = self.wd.find_element(By.CSS_SELECTOR, '.add-one-form > .field:nth-child(3) >input')ele.clear()if minFee:ele.send_keys(minFee)#输入最小消费ele =  self.wd.find_element(By.CSS_SELECTOR, '.add-one-form > .field:nth-child(4) >input')ele.clear()if estFee:ele.send_keys(estFee)#输入预估消费# 三者都有描述, 用xpath而不用 .field:nth-child 因为后付费-上报业务量 次序会变if desc:ele =  self.wd.find_element(By.XPATH,"//*[@class='add-one-submit-btn-div']/preceding-sibling::*[1]/input")ele.clear()ele.send_keys(desc)#输入对应描述# 费率填写if ruleType == '预付费-下发费用':# 没有费率设置passelif ruleType == '后付费-上报业务量':# 先删除上次添加遗留的费率self.wd.implicitly_wait(3)  # 先修改短等待时间while True:eles = self.wd.find_elements(By.CSS_SELECTOR, '.fee-rate span:last-child')if eles:eles[0].click() #删除之前的费率time.sleep(0.5)else:breakself.wd.implicitly_wait(3)  # 再改回来for one in feeRate:#遍历每个费率块self.wd.find_element(By.CSS_SELECTOR,'.fee-rate-list button').click()#锚定整个框entry = self.wd.find_element(By.CSS_SELECTOR,'div.fee-rate:nth-last-child(2)')# 输入业务码entry.find_element(By.CSS_SELECTOR, 'input:nth-of-type(1)').send_keys(one[0])# 输入计费单位entry.find_element(By.CSS_SELECTOR, 'input:nth-of-type(2)').send_keys(one[1])# 输入单位价格entry.find_element(By.CSS_SELECTOR, 'input:nth-of-type(3)').send_keys(one[2])elif ruleType == '预付费-下发业务量':#锚定整个框entry = self.wd.find_element(By.CSS_SELECTOR, 'div.fee-rate')# 输入计费单位entry.find_element(By.CSS_SELECTOR, 'input:nth-of-type(1)').send_keys(feeRate[0])# 输入单位价格entry.find_element(By.CSS_SELECTOR, 'input:nth-of-type(2)').send_keys(feeRate[1])else:raise Exception('ruleType 参数值错误')# 确定提交self.wd.find_element(By.CSS_SELECTOR, '.add-one-submit-btn-div .btn').click()self.wd.implicitly_wait(3)#业务部分查询首页def get_first_page_svc_rules(self):time.sleep(1)self.wd.implicitly_wait(0)items = self.wd.find_elements(By.CSS_SELECTOR,'.result-list-item-info')self.wd.implicitly_wait(10)rules = []for item in items:nameValueList = item.find_elements(By.CSS_SELECTOR, '.field>.field-name, .field>.field-value')itemInfo = []for idx, _ in enumerate(nameValueList):if (idx+1) % 2 == 0:nameEle,valueEle = nameValueList[idx-1], nameValueList[idx]if nameEle.text == '规则内容':ruleContent = {}sfns = valueEle.find_elements(By.CSS_SELECTOR,'.sub-field-name')for sfnEle in sfns:sfn = sfnEle.textsfvEle = sfnEle.find_element(By.XPATH, "following-sibling::*[1]")if sfn == '费率':ruleContent[sfn] = sfvEle.textelse:ruleContent[sfn] = sfvEle.textitemInfo.append(ruleContent)else:itemInfo.append(valueEle.text)rules.append(itemInfo)return rules#删除第一个项目def del_first_item(self) -> bool:self.wd.implicitly_wait(0)delBtn = self.wd.find_elements(By.CSS_SELECTOR,'.result-list-item:first-child .result-list-item-btn-bar span:first-child')self.wd.implicitly_wait(10)if not delBtn:return FalsedelBtn[0].click()self.wd.switch_to.alert.accept()return True

4.2自动化测试脚本代码-业务规则

注意事项跟3.2的商品的自动化测试脚本类似

from selenium.webdriver.common.by import By
import time,pytest
from lib.webUI_smp import smpUI
from lib.cfg import *@pytest.fixture(scope='module')
def inServiceRuleMgr():print('** inServiceRuleMgr setup **')smpUI.login('byhy','sdfsdf' )smpUI.wd.get(SMP_URL_SERVICE_RULE)yield@pytest.fixture()
def delAddedServiceRule():yieldprint('** 删除添加的业务规则')smpUI.del_first_item()@pytest.mark.parametrize('svcname, svctype,paymin,pay, svcdesc,jifeidanwei,feilv', [("全国-电瓶车充电费率1", "预付费-下发业务量", "0.1","2","全国-电瓶车充电费率1的描述",['千瓦时', '1'],None),#添加预付费-下发业务量])
def test_SMP_service_rule_001(svcname, svctype,paymin,pay, svcdesc,jifeidanwei,feilv,inServiceRuleMgr, delAddedServiceRule):# 点击添加按钮topBtn = smpUI.wd.find_element(By.CSS_SELECTOR,'.add-one-area > span')if topBtn.text == '添加':topBtn.click()smpUI.add_svc_rule(svcname, svctype,paymin,pay, jifeidanwei,svcdesc)dms = smpUI.get_first_page_svc_rules()assert dms[0][:3] == [svcname, svctype, {'最小消费': paymin, '预估消费': pay, '费率': f'单位:{jifeidanwei[0]} \n单价:{jifeidanwei[1]}'}]@pytest.mark.parametrize('svcname, svctype,paymin,pay, svcdesc,jifeidanwei,feilv', [("南京-洗车机费率1", "预付费-下发费用", "2","10","南京-洗车机费率1的描述",None,None),#预付费-下发费用])
def test_SMP_service_rule_101(svcname, svctype,paymin,pay, svcdesc,jifeidanwei,feilv,inServiceRuleMgr, delAddedServiceRule):# 点击添加按钮topBtn = smpUI.wd.find_element(By.CSS_SELECTOR,'.add-one-area > span')if topBtn.text == '添加':topBtn.click()smpUI.add_svc_rule(svcname, svctype,paymin,pay,svcdesc)dms = smpUI.get_first_page_svc_rules()assert dms[0][:3] == [svcname, svctype, {'最小消费': paymin, '预估消费': pay}]@pytest.mark.parametrize('svcname, svctype,paymin,pay, svcdesc,jifeidanwei,feilv', [("南京-存储柜费率1", "预付费-下发业务量", None,None,None,None,[['100L','小时','2']]),#添加预付费-下发业务量,['50L','小时','1'],['10L','小时','0.5']])
def test_SMP_service_rule_201(svcname, svctype,paymin,pay, svcdesc,jifeidanwei,feilv,inServiceRuleMgr, delAddedServiceRule):# 点击添加按钮topBtn = smpUI.wd.find_element(By.CSS_SELECTOR,'.add-one-area > span')if topBtn.text == '添加':topBtn.click()smpUI.add_svc_rule(svcname, svctype, paymin, pay,  svcdesc, feilv)dms = smpUI.get_first_page_svc_rules()assert dms[0][:3] == [svcname, svctype, {'业务码': f'单位:{feilv[0]} \n计费单位:{feilv[1]} \n单位价格:{feilv[2]}'}]

还有部分没粘上去,万变不离其宗,还要接口自动化测试,这里先不写,下次再写。 

相关文章:

UI自动化测试示例:python+pytest+selenium+allure

重点应用是封装、参数化: 比如在lib文件夹下,要存储封装好的方法和必要的环境变量(指网址等) 1.cfg.py:封装网址和对应的页面 SMP_ADDRESS http://127.0.0.1:8234SMP_URL_LOGIN f{SMP_ADDRESS}/login.html SMP_URL_DE…...

C/C++ 编程小工具

编写了 tools.h 和 tools.cpp&#xff0c;用于 Debug、性能测试、打印日志。 tools.h #ifndef TOOLS_H #define TOOLS_H#include <time.h> #include <fstream> #include <iostream> #include <random> #include <chrono> #include <vector&…...

第四十二章 使用 WS-ReliableMessaging

文章目录 第四十二章 使用 WS-ReliableMessaging从 Web 客户端发送一系列消息 第四十二章 使用 WS-ReliableMessaging IRIS 支持 WS-ReliableMessaging 规范的部分内容&#xff0c;如简介中所述。此规范提供了一种按顺序可靠地传递一系列消息的机制。本页介绍如何手动使用可靠…...

利士策分享,婚姻为何被称为大事?

利士策分享&#xff0c;婚姻为何被称为大事&#xff1f; 在历史的长河中&#xff0c;婚姻一直被视为人生中的头等大事&#xff0c;这一观念跨越时空&#xff0c;深深植根于各种文化和社会结构中。 古人为何将婚姻称为“大事”&#xff0c;这背后蕴含着丰富的社会、文化和心理寓…...

malloc源码分析之 ----- 你想要啥chunk

文章目录 malloc源码分析之 ----- 你想要啥chunktcachefastbinsmall binunsorted binbin处理top malloc源码分析之 ----- 你想要啥chunk tcache malloc源码&#xff0c;这里以glibc-2.29为例&#xff1a; void * __libc_malloc (size_t bytes) {mstate ar_ptr;void *victim;vo…...

软考系统分析师知识点五:数据通信与计算机网络

前言 今年报考了11月份的软考高级&#xff1a;系统分析师。 考试时间为&#xff1a;11月9日。 倒计时&#xff1a;32天。 目标&#xff1a;优先应试&#xff0c;其次学习&#xff0c;再次实践。 复习计划第一阶段&#xff1a;扫平基础知识点&#xff0c;仅抽取有用信息&am…...

windows客户端SSH连接ubuntu/linux服务器,三种网络连接:局域网,内网穿透(sakuraftp),虚拟局域网(zerotier)

windows客户端SSH连接ubuntu/linux服务器&#xff0c;三种网络连接&#xff1a;局域网&#xff0c;内网穿透&#xff08;sakuraftp&#xff09;&#xff0c;虚拟局域网&#xff08;zerotier&#xff09; 目录 SSH简述、三种网络连接特点SSH简述局域网内连接内网穿透&#xff08…...

Python 工具库每日推荐【openpyxl 】

文章目录 引言Python Excel 处理库的重要性今日推荐:openpyxl 工具库主要功能:使用场景:安装与配置快速上手示例代码代码解释实际应用案例案例:自动生成月度销售报告案例分析高级特性条件格式数据验证扩展阅读与资源优缺点分析优点:缺点:总结【 已更新完 TypeScript 设计…...

本地生活服务项目入局方案解析!本地生活服务商系统能实现怎样的作业效果?

当前&#xff0c;各大平台的本地生活服务业务日渐兴盛&#xff0c;提高创业者入局意向的同时&#xff0c;也让本地生活服务项目有哪些等问题也成为了多个创业者社群中的热议对象。而从目前的讨论情况来看&#xff0c;在创业者们所询问的众多本地生活服务项目中&#xff0c;通过…...

ML 系列:【13 】— Logistic 回归(第 2 部分)

文章目录 一、说明二、挤压方法三、Logistic 回归中的损失函数四、后记 一、说明 ​ 在这篇文章中&#xff0c;我们将深入研究 squashing 方法&#xff0c;这是有符号距离方法&#xff08;第 12节&#xff09;的一种很有前途的替代方案。squashing 方法通过提供增强的对异常值…...

45岁被裁员的程序员,何去何从?

在当今快速变化的技术行业&#xff0c;职业生涯的稳定性受到挑战。在45岁被裁员&#xff0c;对很多程序员来说&#xff0c;可能是一种惊慌失措的体验。然而&#xff0c;这个阶段也可以被视为一个重新审视和调整方向的机会。本文将对可能的出路进行全方位的分析&#xff0c;并提…...

云计算Openstack Neutron

OpenStack Neutron是OpenStack云计算平台中的网络服务组件&#xff0c;它为OpenStack提供了强大的网络连接功能。 一、基本概念 Neutron是一个网络服务项目&#xff0c;旨在为OpenStack提供网络连接。它允许用户创建和管理虚拟网络&#xff0c;包括子网、路由、安全组等&…...

PointNet++网络详解

数据集转换 数据集转换的意义在于将原本的 txt 点云文件转换为更方便运算的npy点云文件&#xff0c;同时&#xff0c;将原本的xyzrgb这 6 个维度转换为xyzrgbc&#xff0c;最后一个c维度代表该点云所属的类别。 for anno_path in anno_paths:print(anno_path)try:elements a…...

Java | Leetcode Java题解之第459题重复的子字符串

题目&#xff1a; 题解&#xff1a; class Solution {public boolean repeatedSubstringPattern(String s) {return kmp(s s, s);}public boolean kmp(String query, String pattern) {int n query.length();int m pattern.length();int[] fail new int[m];Arrays.fill(fa…...

【动态规划-最长公共子序列(LCS)】【hard】力扣1092. 最短公共超序列

给你两个字符串 str1 和 str2&#xff0c;返回同时以 str1 和 str2 作为 子序列 的最短字符串。如果答案不止一个&#xff0c;则可以返回满足条件的 任意一个 答案。 如果从字符串 t 中删除一些字符&#xff08;也可能不删除&#xff09;&#xff0c;可以得到字符串 s &#x…...

‌图片编辑为底片,智能工具助力,创作精彩视觉作品

在当今数字化时代&#xff0c;图像编辑已成为表达创意和美化视觉作品的重要手段。借助智能工具&#xff0c;即使是初学者也能轻松驾驭图片编辑。接下为大家展示图片编辑为底片图片的效果。 1.打开“首助编辑高手”&#xff0c;选择这里“图片批量处理”版块页面上 2.导入保存有…...

机器学习/数据分析--用通俗语言讲解时间序列自回归(AR)模型,并用其预测天气,拟合度98%+

时间序列在回归预测的领域的重要性&#xff0c;不言而喻&#xff0c;在数学建模中使用及其频繁&#xff0c;但是你真的了解ARIMA、AR、MA么&#xff1f;ACF图你会看么&#xff1f;&#xff1f; 时间序列数据如何构造&#xff1f;&#xff1f;&#xff1f;&#xff0c;我打过不少…...

回溯算法之值子集和问题详细解读(附带Java代码解读)

子集和问题&#xff08;Subset Sum Problem&#xff09; 是一个经典的组合优化问题。问题可以这样描述&#xff1a; 给定一个整数集合和一个目标整数 target&#xff0c;我们需要从集合中选出若干个整数&#xff0c;使它们的和等于 target。如果这样的子集存在&#xff0c;返回…...

mysql游标的使用

说明&#xff1a; 虽然我们也可以通过筛选条件 WHERE 和 HAVING&#xff0c;或者是限定返回记录的关键字 LIMIT 返回一条记录&#xff0c;但是&#xff0c;却无法在结果集中像指针一样&#xff0c;向前定位一条记录、向后定位一条记录&#xff0c;或者是 随意定位到某一条记录 …...

linux udev详解

1.概念介绍 1.1sysfs文件系统 Linux 2.6以后的内核引入了sysfs文件系统&#xff0c;sysfs被看成是与proc、devfs和devpty同类别的文件系统&#xff0c;该文件系统是一个虚拟的文件系统&#xff0c;它可以产生一个包括所有系统硬件的层级视图&#xff0c;与提供进程和状态信息…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...