使用 Python 进行测试(5)测试的类型

总结

和我一起唱!
冒烟测试,让你快速失败;
回归测试,不打破过去;
健全性检查,保留所拥有;
集成测试,处理副作用;
端到端,永无尽头!
回测,所有的东西!
property tests have pros and cons, But they’ll guarantee your slot at PyCon. (属性测试有利有弊,但会保证你在PyCon的位置)

在这里插入图片描述

你知道的,命名是个麻烦事

我们今天会介绍一些行话(黑话),目的是让你了解测试的类别。

我们不会涵盖的内容

测试是一个广阔的领域。
检查类型提示是一种测试,linting 也是如此。将软件交到用户手中,看看他们如何使用它也是测试。有时你放一个摄像头,称之为人体工程学/可用性测试,有时你把它发布给一组选定的用户,并称之为alpha/beta测试,有时你把它随机施加到你的生产区域的一个子集,让每个人都感到困惑。这就是 A/B 测试。

一些公司有专门的部门来手动验证软件,他们可能称之为质量测试或验收测试。我有一些朋友根本没有自动化测试,但在每次发布之前,他们都会点击他们应用程序上的每个按钮。是的,这也是测试。

然后你有安全测试,以及各种模糊测试、红队和对抗性压力。再次测试。

还没完。将系统置于预期的压力下,这就是负载测试。把它放在极端的压力下,这就是压力测试。从长远来看,检查它在这些压力下的表现,这就是浸泡测试。看看当这个压力突然变化时它的表现,这就是尖峰测试。所有这些都被归入性能测试的保护伞下。

拔掉服务器是一种测试形式,听说过混沌猴子吗?

甚至审计也是一种测试形式。

由于我不是要写 900 页的三部曲,所以我将坚持单元测试集成测试端到端测试属性测试。这已经很多了,我们可能需要为每个人写一篇文章。此外,大多数人永远不会在进行所有这些类型测试的环境中工作。成本是巨大的,只有非常大的公司才能负担得起整个套餐。

单元测试(Unit tests)

当人们说测试时,通常说的就是这个。
如果你去维基百科,会看到:

单元测试,又名组件或模块测试,是一种软件测试形式,通过它测试隔离的源代码以验证预期行为。
单元测试描述了在单元级别运行的测试,以对比集成或系统级别的测试。

so,你隔离了一部分代码,进行测试,这部分代码成为单元(unit)。
什么部分?怎么隔离?怎么测试?维基百科进一步告诉我们:

单元通常意味着相对较少的代码量;可以与代码库的其余部分隔离的代码,这些代码库可能是一个庞大而复杂的系统。在过程编程中,单元通常是一个函数或模块。在面向对象编程中,单元通常是一个方法、对象或类。

所以基本上,你可以测试一个函数、一个方法、一个对象、一个类或一个模块。就像你可以驾驶三轮车、自行车、汽车、卡车或星际飞船一样。与银河系的其他其他驱动器隔离开来。

冒烟测试(Smoke testing)

冒烟测试是非常基本的初步测试,用于检查软件的基本功能是否正常。这基本上是为了节省你的时间:如果失败了,那么研究细节就没有意义了。

这是我经常写的第一个单元测试:

def test_import():from the_module import main_entry_point

为什么?因为 Python 被导入陷阱所困扰: sys.path 、循环依赖关系、阴影,应有尽有。导入可能会在测试之外失败,但这样我就不会有测试报告,我的测试会崩溃。如果我的项目根本没有加载,这个报告干净,没有歧义。这不仅适用于我,也适用于我的后辈搞砸了,不得不在聊天中报告一些事情。我可以告诉他们先运行这个测试。

冒烟测试有多种形式,就像我说的,它是一个去频谱。它不仅适用于单元测试,还可以进行端到端的冒烟测试,例如运行 CLI --version 并查看它是否返回错误代码。

使用冒烟测试有两个原因:

  • 作为测试的起点,它容易读写,并让人们参与进来。
  • 节省时间,如果冒烟出错了,就不用浪费时间调试更小的东西了。

回归测试

回归测试的主要好处是:保证不会破坏已有的好代码。

例如:

def test_add_strings(setup_and_tear_down):result = add("1", "2")assert result == "12"

这是一个回归测试,如果正确修改了代码,该测试应该同意通过。

健全性测试(Sanity tests)

回归测试的另一面是健全性检查:你确保特定的东西按预期工作。它节省了开发时间,而不是一次又一次地手动运行它,您可以将其委托给测试机器。它让您高枕无忧。它迫使你使用代码的 API,从而了解你的设计带来的权衡。当然,它会对规范的合规性进行编码,或者表明错误修复确实可以修复错误。

通常,回归测试只是旧的健全性检查。

我交替使用它们,对我来说这是一回事,这更像是上下文和词汇的问题,而不是实际的划分。但是你知道极客,我们喜欢分类法。

啊,我在开玩笑,我两者都不用。当我谈论它们时,我只是说“单元测试”,或者只是“测试”。团队知道。

单元测试的范围

我将在另一篇文章中专门讨论单元测试的良好实践。现在,假设单元测试是“不太大”的测试。在这一点上,我站在维基百科的一边。此外,大多数人倾向于同意单元测试是那些几乎没有副作用的单元测试,尤其是 I/O,例如网络调用、文件系统访问等。
如果你将一些不可变的参数传递给单个函数并检查结果,你将很难找到有人会认为这不是一个单元测试。

集成测试(Integration tests)

集成测试是检查“比单元测试更多,但比端到端少,并可以接受副作用”的测试。这是确切的科学定义。不要检查。

他们的目标是查看几个组件是否协同工作。比如,模型是否从缓存中加载?API 是否检查权限?
所以这是一个集成测试:

def test_user_authentication():user = auth_service.authenticate("username", "password")assert user is not None

因为尽管只有几行,但它对系统进行了大量操作,并且实际上它调用了另一个系统:数据库。
您希望集成测试易于单独运行,因为:

  • 它们比单元测试慢
  • 可能有副作用
  • 可能有肮脏的mock
  • 更脆弱

然而,在现场,它们只是混在一大堆测试中,与单元测试混合在一起是很常见的。毕竟,它们还可以检查回归或健全性,而且它们看起来很像单元测试。如果可以,请将它们放在单独的目录中,使用装饰器标记它们,或使用命名约定,以便可以筛选它们。

不幸的是,这并不总是可能的。坦率地说,并不总是可取的。请记住,这完全与目标和约束有关。如果运行整个测试套件需要 4 分钟以上,但将整个测试套件分开会花费很多,您可能不在乎。
分离的主要好处是迫使开发人员考虑其组件的纯度。缺点是开发人员可能过于关注组件的纯度。

许多项目都会有一个巨大的测试目录,其中大部分是集成测试,很少有单元测试,将整个 blob 称为“测试”,而且它们做得很好。不要对此过于强调。它可能是一个非常耦合的设计的标志,同样,这可能是一件好事,也可能是一件坏事,这取决于你的环境。不过,这值得研究,因为它可能会破坏一个项目。

现在,在美妙的 IT 世界中,总有一个问题。集成也用于“持续集成(continuous integration, CI)”的上下文中,即每次推送新代码时,在所有支持的平台上打包、安装和运行软件以及所有测试的做法。想想 GitHub Actions、Gitlab CI、Azure Pipelines、Travis、Jenkins…我们不想让彼此之间的沟通变得太容易,不是吗?
对于一个小团队和项目来说,持续集成是矫枉过正的。在发布之前进行手动检查阶段就足够了。使用 nox + doit 等工具可以轻松完成,以后您可以随时从该工具迁移到 CI。事实上,我的大多数 CI 只是在幕后打电话,因为我讨厌充满激情的模板化 YAML,并且每周都有撒旦仪式专门诅咒想出它们的人。
当您成长时,CI 在避免人为错误、执行策略、管理复杂性等方面变得方便。一旦您进行了大量的兼容性测试以检查不同的 Python 版本、浏览器、设备和操作系统,这绝对是无价的。但是,您公司的 Web API 精确地运行在 CentOS 6 + Python 3.5.1 上,您与一个 3 人团队一起开发,都在推动主 Git 分支,绝对可以推迟采用。

端到端测试(End-to-end tests)

简称为e2e,它是一种测试形式,试图以用户的方式执行系统的大部分内容。
让我们以联系表单为例,以及如何对其进行端到端测试:

import pytest
from playwright.sync_api import sync_playwright
from contact.models import ContactMessage@pytest.mark.django_db
def test_contact_form_submission(playwright_context):# playwright is a lib to manipulate a web browser from pythonwith sync_playwright() as playwright:# Start a real web browser with JS support and actually# navigate to the sitebrowser = playwright.chromium.launch()context = browser.new_context()page = context.new_page()# Assume the server has been started somewhere elsepage.goto("http://localhost:8000/contact")# Fill the contact formpage.fill('#name', 'John Doe')page.fill('#email', 'johndoe@example.com')page.fill('#message', 'Hello, this is a test message.')page.click('button[type="submit"]')# Wait for the form to be submitted and confirmation message to appearpage.wait_for_selector('.success-message')browser.close()# Check if the contact message exists in the databaseassert ContactMessage.objects.filter(name='John Doe',email='johndoe@example.com',message='Hello, this is a test message.').exists()

您会注意到:

  • 它使用真正的浏览器、HTML、CSS 和 JS 测试前端。
  • 它执行 DOM 并形成交互。
  • 它检查 HTTP 堆栈,因为它发出真正的 POST 请求。
  • 它运行您的后端代码、验证、身份验证等。
  • 它确保数据库确实是最新的。
  • 它甚至可以确保响应按预期返回。

它们是一个很棒的 canari,可以快速告诉您是否会影响大量用户的东西正在疯狂运行。他们会告诉你,如果你破坏了UI,让人们感到困惑。他们会告诉你,如果你的集成测试错过了房间里的大象。他们会告诉你,如果你一直有错误的期望,并让你立足于现实。
有一些严肃的批评者对端到端测试咆哮。他们说它们很脆,维护成本高。

我同意它们在编写、读取和调试方面很混乱,而且工具可能会更好。

但他们脆弱的名声也是许多团队有的可怕习惯的结果,那就是破坏用户空间。

“快速行动,打破常规”,“尽早发布,经常发布”,“功能标志”以及所有那些非常聪明和成功的人卖给你的东西。你知道他们也做什么吗?让用户感到困惑,破坏客户的生产力,将支持变成猫捉老鼠的游戏,总而言之,粉碎了您的可靠性光环。

现在,我了解到,在产品的早期阶段,e2e测试基本上是一次性的。你正在学习,你没有稳定性保证,等等。需要保持灵活、精益和快速。

通常,只有少数几个可以缓解这种情况。主要代码路径。改变 10 个测试并不是世界末日,它会很快发现很多问题。

但是一旦你的产品稳定了,我发现端到端的测试可以让你保持诚实:如果你破坏了其中的200个测试,并且它们突然要花很多钱来更新,那么你可能正在做一些对用户不利的事情。

它们也是非技术人员能够很好地理解并可以做出贡献的测试。他们讲述用户故事。

但是,是的,它们很难书写和阅读。副作用、时间、混合上下文和跨越边界使它们变得混乱。我们也只有马马虎虎的工具包,测试 GUI 或 TUI 充其量只是我。如果您必须测试 PDF 输出,愿上帝怜悯。

此外,它们又慢又重,你当然不想在 Git 预提交钩子上运行它们。

尽早做 e2e,但只是一点点。甚至可能只有一个。这样可以保持多汁的股息,并且较低的进入成本。即使对于 CLI,也可以查看此示例中的 ROI,该示例用于测试发送 SMS 警报的命令行工具:

import pytest
import subprocess
import time
from twilio.rest import Client# Twilio is a service that let you send text messages programmatically
account_sid = os.environ['TWILIO_SID']
auth_token = os.environ['TWILIO_TOKEN']
to_number = os.environ['TEST_USER_PHONE_NUMBER']
from_number = os.environ['TEST_SERVICE_PHONE_NUMBER']def test_send_sms():test_message = "This is a test message"# Run the CLI command in a different processsubprocess.run(['python', 'send_sms.py', test_message, to_number], check=True)# Wait for the message to be sent and receivedtime.sleep(10)twilio_client = Client(account_sid, auth_token)messages = twilio_client.messages.list(to=to_number, from_=from_number, limit=1)assert len(messages) > 0assert messages[0].body == test_message

我们行使一切,参数解析,网络调用,接收,消息完整性,我们的帐户订阅已支付(尽管它非常重要并且搞砸了世界各地的许多公司,但没有人测试过)…

当然,它有很多问题:

  • 网络或 Twilio 可能会瘫痪。
  • sleep时间可能会有一天关闭。
  • 我们不依赖向该号码发送消息的其他任何内容。
  • 如果你搞砸了,比如引入一个循环调用该测试的错误,它可能会花费你很多钱。

但是你不能躲在关注点的分离后面,如果链条的任何部分薄弱,你的产品坏了,你就会知道。

一旦产品成熟,就要加倍努力。将它们与您的单元和集成测试保持良好分离。它们不应该相互影响。您应该能够破坏私有 API,而不会完全影响 e2e。您应该能够更改您练习 UI 的方式,而无需使用较小的部分来实现它。

最后,我再说一遍,请记住,测试是一个频谱。您不必处于绝对的一端,端到端才有价值。使用 FastAPI 查看该示例:

from fastapi import FastAPI
from fastapi.testclient import TestClient
from our_project.site import fast_api_appclient = TestClient(fast_api_app)def test_read_user_profile():response = client.get("/me")assert response.status_code == 200assert response.json() == {"username": "BiteCode", "id": "987890789790"}

它测试整个 API 端点,包括数据库调用,但不会旋转真实服务器,因为它使用创建 Python HTTP 请求对象而不是解析字节字符串的测试客户端。它也没有执行真正的客户端解析响应。

Is that e2e? Is that integration testing? Maybe it’s Maybelline.
谁在乎,它很有用。
把它放在其中一个文件夹中,同意你的团队始终如一地这样做,然后转到下一个可交付成果。

回测(Backtesting)

回溯测试是测试中被忽视的领域,你会发现它主要发生在机构中的大型、有风险的长跑运动员身上。

这是一个积累输入和输出的过程,你知道这些输入和输出应该对你的系统有效,然后定期向它提供整个数据集,以检查它是否仍然像这样运行。

它是回归和端到端测试的混合体,两者各有利弊。

它成本高昂、速度慢,并且会使您的功能集变得石化。

但是,您这样做的时间越长,您的系统就越可靠,尤其是在错误和边缘情况的长尾中。有些用户会喜欢你,因为你一直在他们身边,有些用户会讨厌你,因为你从未现代化。此外,您还必须大量处理架构版本控制。

简而言之,它非常适合银行支付系统,而对于热门的启动手机应用程序来说完全不够用。

它是什么样子的?

想象一下,一个交易者想要改变他的加密货币机器人行为,但希望看到在相同的市场下,与之前的策略相比,这将如何影响他的收益:

import pandas as pd# Load historical data# Kryll is a veteran token that powers an automated trading platform, 
# which, funnily, provide a UI to create strategies and backtest 
# them without code. But pandas is free :)df = pd.read_csv('kryll_historical_data.csv', parse_dates=['Date'])
df.set_index('Date', inplace=True)# Calculate moving averages.
short_window = 40
long_window = 100df['SMA40'] = df['Close'].rolling(window=short_window, min_periods=1).mean()
df['SMA100'] = df['Close'].rolling(window=long_window, min_periods=1).mean()# Define the trading signals
df['Signal'] = 0
df['Signal'][short_window:] = np.where(df['SMA40'][short_window:] > df['SMA100'][short_window:], 1, 0)
df['Position'] = df['Signal'].diff()# Initialize backtesting variables
initial_capital = 100000.0
positions = pd.DataFrame(index=df.index).fillna(0.0)
portfolio = pd.DataFrame(index=df.index).fillna(0.0)# Simulate trades. This is BS, but have you worked in finance?
positions['Kryll'] = df['Position'] * initial_capital / df['Close']
portfolio['Positions'] = (positions.multiply(df['Close'], axis=0)).sum(axis=1)
portfolio['Cash'] = initial_capital - (positions.diff().multiply(df['Close'], axis=0)).sum(axis=1).cumsum()
portfolio['Total'] = portfolio['Positions'] + portfolio['Cash']# Calculate returns
portfolio['Returns'] = portfolio['Total'].pct_change()# Display the portfolio and performance metrics
print(portfolio)# Plot the results
import matplotlib.pyplot as pltfig, ax = plt.subplots(figsize=(12, 8))
ax.plot(df.index, portfolio['Total'], label='Portfolio Value')
ax.plot(df.index, df['Close'], label='Kryll Close Price', alpha=0.5)
ax.set(title='Backtest of SMA Crossover Strategy', xlabel='Date', ylabel='Value')
ax.legend()
plt.show()

我保留了量化代码的美妙风格,包括内联导入,这样你就可以体验到我们的经济所依赖的东西。我在开玩笑,加上我根本没有测试过这个脚本,它更接近伪代码。

回溯测试不一定是完全自动化的,也不一定是一对一的匹配才有用。有时你希望你的系统表现得和以前完全一样,但有时你只是希望趋势大致相似或更好,因为你知道不可能得到完全相同的结果。

这就是它在这里的内容:我们在脚本末尾显示结果的 matplotlib 曲线,因此我们可以直观地检查结果与之前的结果进行比较。

当然,并非所有的回测都是这样的。有些需要完美的对齐并且不涉及人类,但您的数据集越大,它发生的可能性就越小,甚至不可能发生。现实充满了复杂性。

属性测试(Property tests)

也被称为“我们在 PyCon 上看到过,还记得吗?”,因为每个听说过它的人都认为它很酷,但实际这样做的人数接近 Raspberry Pi 上的引脚数量。

这个想法是运行代码,但不是测试结果,而是检查无论输入是什么,通用属性是否仍然为 true。然后,一个工具(在Python中,通常是优秀的假设)将尝试将各种垃圾传递给它,直到它崩溃。
我发誓,这非常有用。

首先选择一个单元测试来练习程序的关键部分。属性测试既缓慢又昂贵,因此您通常从小处着手。您还希望避免副作用,因为代码将以不受控制的方式运行数百万次,因此很难管理因果关系链。这是与一般模糊测试的主要区别,一般模糊测试实际上旨在制造混乱,并且这可能是可取的,尤其是对于安全性而言。

让我们回到本系列文章的第 2 部分中的 add() 示例。我们有:

import randomimport pytest
from the_code_to_test import add@pytest.fixture()
def random_number():yolo = random.randint(0, 10)yield yoloprint(f"\nWe tested with {yolo}")@pytest.fixture()
def setup_and_tear_down():print("\nThis is run before each test")yieldprint("\nThis is run after each test")def test_add_integers(setup_and_tear_down, random_number):result = add(1, 2)assert result == 3result = add(1, -2)assert result == -1assert add(0, random_number) > 0def test_add_strings(setup_and_tear_down):result = add("1", "2")assert result == "12"def test_add_floats():result = add(0.1, 0.2)assert result == pytest.approx(0.3)def test_add_mixed_types():with pytest.raises(TypeError):add(1, "2")

我们怎么知道我们测试了所有边缘情况并找出了所有错误?这当然是不可能的,但我们有多大的信心去追逐所有最明显的目标?
现在你的直觉是,对于这样一个简单的函数,域是相当明显的,我们不可能错过什么。我的意思是,来吧,这是 add() !
但像往常一样,编程是在嘲笑我们的天真,而且有龙。
假设在这里可以提供帮助,所以让我们在拥有 pip installed hypothesis-pytest 条件后再创建一个测试:

import pytest
from the_code_to_test import add
from hypothesis import given, strategies as st@given(st.one_of(st.integers(), st.floats()), st.one_of(st.text(), st.integers(), st.floats()))
def test_add_mixed_types_property(a, b):if isinstance(a, (int, float)) and isinstance(b, (int, float)):result = add(a, b)assert result == a + belse:with pytest.raises(TypeError):add(a, b)

我不会在这里详细介绍,会有一篇专门介绍属性测试的文章。但从本质上讲,我们告诉假设我们想检查属性,说明“使用 add() 时,要么我们传递相同的类型,结果为相同的类型,要么我们没有传递相同的类型,并且存在错误”。

理智行为:添加字符串,取回字符串。添加浮点数,取回浮点数。添加一个字符串和一个 int,这是一个错误。
从这个测试中,假设将生成大量输入数据的组合,运行代码并试图证明我们只不过是愚蠢的小猿猴,愚蠢地相信我们一直在控制之中。
可能出什么问题?
房间里所有因这个问题而遭受巨大痛苦的数据科学家,都已经以一种心爱的印度面包的形式尖叫着答案,但讨厌浮点值:

a = 0, b = nan@given(st.one_of(st.integers(), st.floats()), st.one_of(st.text(), st.integers(), st.floats()))def test_add_mixed_types_property(a, b):if isinstance(a, (int, float)) and isinstance(b, (int, float)):result = add(a, b)
>           assert result == a + b
E           assert nan == (0 + nan)
E           Falsifying example: test_add_mixed_types_property(
E               a=0,
E               b=nan,  # Saw 1 signaling NaN
E           )

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

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

相关文章

Django使用django-apscheduler实现定时任务

定时任务可以在后台定时执行指定的代码,避免了很多人为操作。下面是在Django项目中如何使用定时任务的具体操作流程。 我在这里使用的 django-apscheduler库来实现定时任务。 一、安装 django-apscheduler pip install django-apscheduler二、在项目的setting.py…

仿真模拟--telnet服务两种认证模式(自作)

自己做的笔记,有问题或看不懂请见解一下~ 目录 两个路由器间实现telnet服务(password认证模式) server client 两个路由器间实现telnet服务(aaa认证模式) server client 改名 tab键补齐 不会就扣问号 ? save 两个路由器间实现telnet服务…

有哪些去手写免费的软件?软件介绍

有哪些去手写免费的软件?在数字化时代,高效处理文字信息已成为学习和工作中不可或缺的一环。对于需要频繁处理手写试卷、笔记的用户来说,一款好的去手写软件无疑能大大提升效率。今天,我们就来推荐三款免费的去手写软件&#xff0…

CentOS 8.5 - 配置ssh的免密登录

文章目录 生成ssh密钥公钥内容放入服务器 生成ssh密钥 在本地主机安装 ssh工具,并生成公钥、私钥。 # 命令行输入 ssh-keygen -r rsa# 会在当前用户的家目录下生成一个.ssh目录公钥内容放入服务器 将上一步生成的id_rsa.pub公钥的内容复制到远程服务器 # 编辑文…

虚拟机安装JDK11操作教程

1、新建/usr/java目录 mkdir /usr/java 2、将jdk-11文件上传/usr/java目录 3、解压jdk-11文件 tar -zxvf jdk-11_linux-x64_bin.tar.gz 4、编辑配置文件,配置环境变量 vi /etc/profile 在打开的文件末尾添加 export JAVA_HOME/usr/java/jdk-11 export JRE_HOM…

对30年国债利率破2.5%的复盘反思

短期看,以月为维度,长端和超长端利率依然具有较强的向下突破的惯性;中期看,以季为维度,长端依然面临向下赔率不足的约束,但调整需要多重利空共振的契机。 短期看多,逢高配置”的四点逻辑 逻辑一…

linux——ansible实验

要求 0.进入servera进行准备工作,做一些清理 1)停止httpd服务,清除httpd软件包、配置文件、主页文件 2)清理/etc/hosts文件中的内容,只保留最上面默认的两行 (127.0.0.1和::1这两行) 1.根据之前…

短信内容关键字被拦截-阿里云通知类短信

通知类短信。地产、留学、招聘、交友、游戏等行业仅支持发送验证码。 注意不要有字眼,替换为相似的词语。否则拦截率很高

如何设计一个点赞系统

首先我们定义出一个点赞系统需要对外提供哪些接口: 1.用户对特定的消息进行点赞; 2.用户查看自己发布的某条消息点赞数量以及被哪些人赞过; 3.用户查看自己给哪些消息点赞过; 这里假设每条消息都有一个message_id, 每一个用户都…

百度安全X盈科全球数据合规服务中心:推进数据安全及合规智能化创新领域深化合作

6月19日,百度安全与盈科全球数据合规服务中心举行合作签约仪式,双方将充分发挥各自优势,在数据安全及合规智能化创新领域深化合作,在遵守国家法律法规和顺应市场规则的前提下,推动地方经济社会发展,促进企业…

(3) cmake编译多个cpp文件

文章目录 概要整体代码运行结果 概要 上一节中实现了对单个cpp文件用cmake编译。这一节升级一下 整体代码 main.cpp #include <iostream> #include "person.h"using namespace std;int main() {person me person("langdaoliu", 28, "engin…

2024考古之还在用原始JDBC开发 手搓 案例 实现一个模块的增删改

JDBC案例 将来如果完成的话 就代表对JDBC里面的知识点全部融会贯通了 其实就是对数据的增删改查 我们入门做不出来前端的内容 很正常 准备环境 建表 use mybatis;create table tbl_brand (id int primary key auto_increment,brand_name varchar(20),company_name varcha…

使用 ZoomEye 找到未启用身份验证的 Jupyter 服务器

一&#xff0e;摘要 在使用Jupyter Notebook和JupyterLab 的过程中&#xff0c;有些用户缺乏安全意识&#xff0c;未启用身份验证功能&#xff0c;导致任何用户都可以直接访问自己的Jupyter服务器&#xff0c;并查看其服务器上的代码和文档。 我们使用ZoomEye 网络空间搜索引…

SBTI认证的申请流程是什么?

SBTI&#xff08;科学基准目标倡议&#xff09;认证的申请流程通常包括以下几个关键步骤&#xff0c;以下是根据参考文章整理出的清晰流程&#xff1a; 咨询和准备阶段&#xff1a; 企业首先需要咨询SBTI认证机构&#xff0c;了解认证的标准和要求&#xff0c;并确定是否有资格…

LDO的原理及测试方法

一、基本结构 这是LM317芯片的核心,这个电路单元称为Bandgap Reference带隙基准源。属于模拟集成电路中的经典电路结构。 LDO拓扑结构图 常见的基本结构 利用VBE的负温度系数,而VT是正温度系数,正负温度系数抵消就的得到稳定的基准参考电压了(三极管的方程VBE=VT*In(lC/IS…

SCI一区TOP|局部强化优化算法(PRO)原理及实现【免费获取Matlab代码】

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;A Taheri受到部分强化效应(PRE)理论启发&#xff0c;提出了局部强化优化算法&#xff08;Partial Reinforcement Optimizer, PRO&#xff09;。 2.算法原理 2.1算法思…

OpenGL绘制Bezier曲面

Bezier的定义 贝塞尔曲面是贝塞尔曲线在二维上的扩展。它由一组控制点定义,通过这些控制点生成光滑的曲面。贝塞尔曲面通常用两个参数 u u u和 v v v来表示,这两个参数的取值范围都在 [0, 1] 之间。 数学表示 P ( u , v ) = ∑ i = 0 n ∑ j = 0 m p i j ⋅ B i , n ( u ) ⋅…

redis-基础篇(1)

黑马redis-基础篇笔记 1. 初识redis REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统&#xff0c;是跨平台的非关系型数据库。Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的…

Mybatis中BaseEntity作用

新建各种对象的时候&#xff0c;一般来说&#xff0c;有几个属性是所有对象共有的&#xff0c;比如说id,is_del&#xff0c;is_enable这些&#xff0c;然后设置一个基础对象&#xff0c;以后新建所有对象的时候都继承它&#xff0c;就省的每次都要写这些共有的属性了

HCIA-速查-ENSP模拟器2步清空配置

需求&#xff1a;清空模拟器配置 清空当前图中配置 步骤1&#xff1a;reset saved-configuration 后输入y确认 步骤2&#xff1a;reboot后输入n否认再输入y确认 验证已经清空配置