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

UnitTesting 单元测试

1. 测试分为两种及详细介绍测试书籍:

  1.1 Unit Test : 单元测试

  - test the business logic in your app : 测试应用中的业务逻辑

  1.2 UI  Test :  界面测试

  - test the UI of your app : 测试应用中的界面

  1.3 测试书籍网址:《Testing Swift》 icon-default.png?t=N7T8https://www.hackingwithswift.com/store/testing-swift

2. ViewModel 单元测试

  2.1 创建 ViewModel,UnitTestingBootcampViewModel.swift

import Foundation
import SwiftUI
import Combine/// 单元测试 ViewModel
class UnitTestingBootcampViewModel: ObservableObject{@Published var isPremium: Bool@Published var dataArray: [String] = []@Published var selectedItem: String? = nillet dataService: NewDataServiceProtocolvar cancellable = Set<AnyCancellable>()init(isPremium: Bool, dataService: NewDataServiceProtocol = NewMockDataService(items: nil)) {self.isPremium = isPremiumself.dataService = dataService}/// 添加子项func addItem(item: String){// 为空不往下执行guard !item.isEmpty else { return }self.dataArray.append(item)}/// 选中项func selectItem(item: String){if let x = dataArray.first(where: {$0 == item}){selectedItem = x}else{selectedItem = nil}}/// 保存项func saveItem(item: String) throws{guard !item.isEmpty else{throw DataError.noData}if let x = dataArray.first(where: {$0 == item}){print("Save item here!!! \(x)")} else {throw DataError.itemNotFound}}/// 错误信息enum DataError: LocalizedError{case noDatacase itemNotFound}/// 请求返回数据func downloadWithEscaping() {dataService.downloadItemsWithEscaping { [weak self] returnedItems inself?.dataArray = returnedItems}}/// 下载用到的组合func downloadWithCombine() {dataService.downloadItemsWithCombine().sink { _ in} receiveValue: { [weak self] returnedItems inself?.dataArray = returnedItems}.store(in: &cancellable)}
}

  2.2 创建测试文件

    当创建项目时,没有选择 Include Tests/包含测试 选项时,需要添加文件去对应项目,不然测试文件会报 No such module 'XCTest' 编译错误

    添加单元测试文件:

    方法一 : 选择项目 -> 菜单栏 Editor -> Add Target... -> 弹出对话框,选择 Test 栏下 -> Unit Testing Bundle -> 填写信息/可默认 -> Finish,完成创建单元测试文件。

    方法二 : 选择项目,点击 PROJECT 列,最下的 + 按钮,弹出对话框,选择 Test 栏下 ,后面步骤与上一致

    创建单元测试文件 UnitTestingBootcampViewModel_Tests.swift

import XCTest
import Combine
/// 导入项目
@testable import SwiftfulThinkingAdvancedLearning// 《Testing Swift》 测试书籍
// 书籍网址: https://www.hackingwithswift.com/store/testing-swift
// Naming Structure: test_UnitOfWork_StateUnderTest_ExpectedBehavior -  结构体命名: 测试_工作单元_测试状态_预期的行为
// Naming Structure: test_[struct or class]_[variable or function]_[expected result] - 测试_[结构体 或者 类的名称]_[类中的变量名 或者 函数名称]_[预期结果 预期值]
// Testing Structure: Given, When, Then - 测试结构: 给定,什么时候,然后final class UnitTestingBootcampViewModel_Tests: XCTestCase {/// 解决多次引用相同的类var viewModel: UnitTestingBootcampViewModel?var cancellables = Set<AnyCancellable>()/// 开始设置数据override func setUpWithError() throws {// Put setup code here. This method is called before the invocation of each test method in the class.viewModel = UnitTestingBootcampViewModel(isPremium: Bool.random())}/// 结束重置数据override func tearDownWithError() throws {// Put teardown code here. This method is called after the invocation of each test method in the class.viewModel = nilcancellables.removeAll()}/// 单元测试函数名,根据命名规则命名:测试_类名称_是否高质量_应该为真func test_UnitTestingBootcampViewModel_isPremium_shouldBeTrue(){// Givenlet userIsPremium: Bool = true// Whenlet vm = UnitTestingBootcampViewModel(isPremium: userIsPremium)// ThenXCTAssertTrue(vm.isPremium)}/// 单元测试函数名 根据命名规则命名:测试_类名称_是否高质量_应该为假func test_UnitTestingBootcampViewModel_isPremium_shouldBeFalse(){// Givenlet userIsPremium: Bool = false// Whenlet vm = UnitTestingBootcampViewModel(isPremium: userIsPremium)// ThenXCTAssertFalse(vm.isPremium)}/// 单元测试函数名 根据命名规则命名:测试_类名称_是否高品质_注入值func test_UnitTestingBootcampViewModel_isPremium_shouldBeInjectedValue(){// Givenlet userIsPremium: Bool = Bool.random()// Whenlet vm = UnitTestingBootcampViewModel(isPremium: userIsPremium)// ThenXCTAssertEqual(vm.isPremium, userIsPremium)}/// 单元测试函数名 根据命名规则命名 - 注入值_压力 / for 循环func test_UnitTestingBootcampViewModel_isPremium_shouldBeInjectedValue_stress(){for _ in 0 ..< 10 {// Givenlet userIsPremium: Bool = Bool.random()// Whenlet vm = UnitTestingBootcampViewModel(isPremium: userIsPremium)// ThenXCTAssertEqual(vm.isPremium, userIsPremium)}}/// 单元测试函数名 根据命名规则命名 - 数组_预期值:为空func test_UnitTestingBootcampViewModel_dataArray_shouldBeEmpty(){// Given// Whenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Then 断言 = 判定XCTAssertTrue(vm.dataArray.isEmpty)XCTAssertEqual(vm.dataArray.count, 0)}/// 单元测试函数名 根据命名规则命名 - 数组_预期值:添加项func test_UnitTestingBootcampViewModel_dataArray_shouldAddItems(){// Givenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Whenlet loopCount: Int = Int.random(in: 1..<100)for _ in 0 ..< loopCount{vm.addItem(item: UUID().uuidString)}// Then 断言 = 判定XCTAssertTrue(!vm.dataArray.isEmpty)XCTAssertFalse(vm.dataArray.isEmpty)XCTAssertEqual(vm.dataArray.count, loopCount)XCTAssertNotEqual(vm.dataArray.count, 0)// GreaterThan 大于XCTAssertGreaterThan(vm.dataArray.count, 0)// XCTAssertGreaterThanOrEqual// XCTAssertLessThan// XCTAssertLessThanOrEqual}/// 单元测试函数名 根据命名规则命名 - 数组_预期值:添加空白字符func test_UnitTestingBootcampViewModel_dataArray_shouldNotAddBlankString(){// Givenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Whenvm.addItem(item: "")// Then 断言 = 判定XCTAssertTrue(vm.dataArray.isEmpty)}/// 单元测试函数名 根据命名规则命名 - 数组_预期值:添加空白字符func test_UnitTestingBootcampViewModel_dataArray_shouldNotAddBlankString2(){// Givenguard let vm = viewModel else {XCTFail()return}// Whenvm.addItem(item: "")// Then 断言 = 判定XCTAssertTrue(vm.dataArray.isEmpty)}/// 单元测试函数名 根据命名规则命名 - 选中项_预期值:开始为空func test_UnitTestingBootcampViewModel_selectedItem_shouldStartAsNil(){// Given// Whenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Then 断言 = 判定XCTAssertTrue(vm.selectedItem == nil)XCTAssertNil(vm.selectedItem)}/// 单元测试函数名 根据命名规则命名 - 选中项_预期值:应该为空 当选择无效项func test_UnitTestingBootcampViewModel_selectedItem_shouldBeNilWhenSelectingInvalidItem(){// Givenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Select valid item : 选择有效项let newItem = UUID().uuidStringvm.addItem(item: newItem)vm.selectItem(item: newItem)// Select invalid item : 选择无效项// Whenvm.selectItem(item: UUID().uuidString)// Then 断言 = 判定XCTAssertNil(vm.selectedItem)}/// 单元测试函数名 根据命名规则命名 - 选中项_预期值:应该选中func test_UnitTestingBootcampViewModel_selectedItem_shouldBeSelected(){// Givenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Whenlet newItem = UUID().uuidStringvm.addItem(item: newItem)vm.selectItem(item: newItem)// Then 断言 = 判定XCTAssertNotNil(vm.selectedItem)XCTAssertEqual(vm.selectedItem, newItem)}/// 单元测试函数名 根据命名规则命名 - 选中项_预期值:选中_压力测试func test_UnitTestingBootcampViewModel_selectedItem_shouldBeSelected_stress(){// Givenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Whenlet loopCount: Int = Int.random(in: 1..<100)var itemsArray: [String] = []for _ in 0 ..< loopCount {let newItem = UUID().uuidStringvm.addItem(item: newItem)itemsArray.append(newItem)}// 随机取一个字符串let randomItem = itemsArray.randomElement() ?? ""// 检查字符串不为空XCTAssertFalse(randomItem.isEmpty)vm.selectItem(item: randomItem)// Then 断言 = 判定XCTAssertNotNil(vm.selectedItem)XCTAssertEqual(vm.selectedItem, randomItem)}/// 单元测试函数名 根据命名规则命名 - 保存项_预期值:输出错误异常_元素没找到func test_UnitTestingBootcampViewModel_saveItem_shouldThrowError_itemNotFound(){// Givenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Whenlet loopCount: Int = Int.random(in: 1..<100)for _ in 0 ..< loopCount {vm.addItem(item: UUID().uuidString)}// Then 断言 = 判定XCTAssertThrowsError(try vm.saveItem(item: UUID().uuidString))XCTAssertThrowsError(try vm.saveItem(item: UUID().uuidString), "Should throw Item Not Found error!") { error in// 返回错误let returnedError = error as? UnitTestingBootcampViewModel.DataError// 判断错误是否相同XCTAssertEqual(returnedError, UnitTestingBootcampViewModel.DataError.itemNotFound)}}/// 单元测试函数名 根据命名规则命名 - 保存项_预期值:输出错误异常_没数据func test_UnitTestingBootcampViewModel_saveItem_shouldThrowError_noData(){// Givenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Whenlet loopCount: Int = Int.random(in: 1..<100)for _ in 0 ..< loopCount {vm.addItem(item: UUID().uuidString)}// Then 断言 = 判定do {try vm.saveItem(item: "")} catch let error {// 返回错误let returnedError = error as? UnitTestingBootcampViewModel.DataError// 判断错误是否相同XCTAssertEqual(returnedError, UnitTestingBootcampViewModel.DataError.noData)}}/// 单元测试函数名 根据命名规则命名 - 保存项_预期值:保存选项func test_UnitTestingBootcampViewModel_saveItem_shouldSaveItem(){// Givenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Whenlet loopCount: Int = Int.random(in: 1..<100)var itemsArray: [String] = []for _ in 0 ..< loopCount {let newItem = UUID().uuidStringvm.addItem(item: newItem)itemsArray.append(newItem)}// 随机取一个字符串let randomItem = itemsArray.randomElement() ?? ""// 检查字符串不为空XCTAssertFalse(randomItem.isEmpty)// Then 断言 = 判定XCTAssertNoThrow(try vm.saveItem(item: randomItem))do {try vm.saveItem(item: randomItem)} catch  {XCTFail()}}/// 单元测试函数名 根据命名规则命名 - 下载数据_预期值:返回选项func test_UnitTestingBootcampViewModel_downloadWithEscaping_shouldReturnItems(){// Givenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Whenlet expectation = XCTestExpectation(description: "Should return items after 3 seconds")// dropFirst: 删除第一个发布 数组值,因为初始化为空数组,取的是第二个数组,模拟服务数据返回的数组vm.$dataArray.dropFirst().sink { returnedItems inexpectation.fulfill()}.store(in: &cancellables)vm.downloadWithEscaping()// Then 断言 = 判定 GreaterThan:大于// 为了安全获取到值,设置等待 5 秒wait(for: [expectation], timeout: 5)XCTAssertGreaterThan(vm.dataArray.count, 0)}/// 单元测试函数名 根据命名规则命名 - 下载数据组合_预期值:返回选项func test_UnitTestingBootcampViewModel_downloadWithCombine_shouldReturnItems(){// Givenlet vm = UnitTestingBootcampViewModel(isPremium: Bool.random())// Whenlet expectation = XCTestExpectation(description: "Should return items after a seconds")// dropFirst: 删除第一个发布 数组值,因为初始化为空数组,取的是第二个数组,模拟服务数据返回的数组vm.$dataArray.dropFirst().sink { returnedItems inexpectation.fulfill()}.store(in: &cancellables)vm.downloadWithCombine()// Then 断言 = 判定 GreaterThan:大于// 为了安全获取到值,设置等待 5 秒wait(for: [expectation], timeout: 5)XCTAssertGreaterThan(vm.dataArray.count, 0)}/// 单元测试函数名 根据命名规则命名 - 下载数据组合_预期值:返回选项func test_UnitTestingBootcampViewModel_downloadWithCombine_shouldReturnItems2(){// Givenlet items: [String] = [UUID().uuidString, UUID().uuidString, UUID().uuidString, UUID().uuidString]let dataService: NewDataServiceProtocol = NewMockDataService(items: items)let vm = UnitTestingBootcampViewModel(isPremium: Bool.random(), dataService: dataService)// Whenlet expectation = XCTestExpectation(description: "Should return items after a seconds")// dropFirst: 删除第一个发布 数组值,因为初始化为空数组,取的是第二个数组,模拟服务数据返回的数组vm.$dataArray.dropFirst().sink { returnedItems inexpectation.fulfill()}.store(in: &cancellables)vm.downloadWithCombine()// Then 断言 = 判定 GreaterThan:大于// 为了安全获取到值,设置等待 5 秒wait(for: [expectation], timeout: 5)XCTAssertGreaterThan(vm.dataArray.count, 0)XCTAssertEqual(vm.dataArray.count, items.count)}
}

3. 模拟请求数据 单元测试

  3.1 创建模拟请求数据类 NewMockDataService.swift

import Foundation
import SwiftUI
import Combine/// 定义协议
protocol NewDataServiceProtocol{func downloadItemsWithEscaping(completion: @escaping (_ items: [String]) -> ())func downloadItemsWithCombine() -> AnyPublisher<[String], Error>
}/// 实现模拟请求数据
class NewMockDataService: NewDataServiceProtocol {let items: [String]init(items: [String]?) {self.items = items ?? ["ONE", "TWO", "THREE"]}/// 模拟网络下载数据 escaping: 转义字符func downloadItemsWithEscaping(completion: @escaping (_ items: [String]) -> ()) {DispatchQueue.main.asyncAfter(deadline: .now() + 2) {completion(self.items)}}/// 下载组合func downloadItemsWithCombine() -> AnyPublisher<[String], Error> {// 数据转换Just(self.items).tryMap({ publishedItems inguard !publishedItems.isEmpty else {throw URLError(.badServerResponse)}return publishedItems}).eraseToAnyPublisher()}
}

  3.2 创建单元测试类 NewMockDataService_Tests.swift

import XCTest
import Combine
/// 导入项目
@testable import SwiftfulThinkingAdvancedLearningfinal class NewMockDataService_Tests: XCTestCase {/// 随时取消控制器var cancellable = Set<AnyCancellable>()override func setUpWithError() throws {// Put setup code here. This method is called before the invocation of each test method in the class.}override func tearDownWithError() throws {// Put teardown code here. This method is called after the invocation of each test method in the class.cancellable.removeAll()}//  单元测试函数名 根据命名规则命名 - 测试_类名_初始化_预期值:正确的设置值func test_NewMockDataService_init_doesSetValuesCorrectly() {// 执行// Given: 给定let items: [String]? = nillet items2: [String]? = []let items3: [String]? = [UUID().uuidString, UUID().uuidString]// When: 时间let dataService = NewMockDataService(items: items)let dataService2 = NewMockDataService(items: items2)let dataService3 = NewMockDataService(items: items3)// Then 然后XCTAssertFalse(dataService.items.isEmpty)XCTAssertTrue(dataService2.items.isEmpty)XCTAssertEqual(dataService3.items.count, items3?.count)}//  单元测试函数名 根据命名规则命名 - 测试_类名_下载转换数据项_预期值:正确的设置值func test_NewMockDataService_downloadItemsWithEscaping_doesReturnValues() {// 执行// Given: 给定let dataService = NewMockDataService(items: nil)// When: 时间var items: [String] = []let expectation = XCTestExpectation()dataService.downloadItemsWithEscaping { returnedItems initems = returnedItemsexpectation.fulfill()}// Then 然后// 等待 5 秒wait(for: [expectation], timeout: 5)// 断言两个数组大小一样XCTAssertEqual(items.count, dataService.items.count)}//  单元测试函数名 根据命名规则命名 - 测试_类名_下载数据项组合_预期值:正确的设置值func test_NewMockDataService_downloadItemsWithCombine_doesReturnValues() {// 执行// Given: 给定let dataService = NewMockDataService(items: nil)// When: 时间var items: [String] = []let expectation = XCTestExpectation()// 下载组合控制dataService.downloadItemsWithCombine().sink { completion inswitch completion{case .finished:expectation.fulfill()case .failure:XCTFail()}} receiveValue: {returnedItems in// fulfill: 完成items = returnedItems}.store(in: &cancellable)// Then 然后// 等待 5 秒wait(for: [expectation], timeout: 5)// 断言两个数组大小一样XCTAssertEqual(items.count, dataService.items.count)}//  单元测试函数名 根据命名规则命名 - 测试_类名_下载数据项组合_预期值:确实失败func test_NewMockDataService_downloadItemsWithCombine_doesFail() {// 执行// Given: 给定let dataService = NewMockDataService(items: [])// When: 时间var items: [String] = []let expectation = XCTestExpectation(description: "Does throw an error")let expectation2 = XCTestExpectation(description: "Does throw URLError.badServerResponse")// 下载组合控制dataService.downloadItemsWithCombine().sink { completion inswitch completion{case .finished:XCTFail()case .failure(let error):expectation.fulfill()//let urlError = error as? URLError// 断言,判定//XCTAssertEqual(urlError, URLError(.badServerResponse))// 错误判断if error as? URLError == URLError(.badServerResponse) {expectation2.fulfill()}}} receiveValue: {returnedItems in// fulfill: 完成items = returnedItems}.store(in: &cancellable)// Then 然后// 等待 5 秒wait(for: [expectation, expectation2], timeout: 5)// 断言两个数组大小一样XCTAssertEqual(items.count, dataService.items.count)}
}

4. 创建单元测试 View,调用测试的 ViewModel UnitTestingBootcampView.swift

import SwiftUI/*1. Unit Test : 单元测试- test the business logic in your app : 测试应用中的业务逻辑2. UI  Test :  界面测试- test the UI of your app : 测试应用中的界面*//// 单元测试
struct UnitTestingBootcampView: View {@StateObject private var vm: UnitTestingBootcampViewModelinit(isPremium: Bool){_vm = StateObject(wrappedValue: UnitTestingBootcampViewModel(isPremium: isPremium))}var body: some View {Text(vm.isPremium.description)}
}struct UnitTestingBootcampView_Previews: PreviewProvider {static var previews: some View {UnitTestingBootcampView(isPremium: true)}
}

相关文章:

UnitTesting 单元测试

1. 测试分为两种及详细介绍测试书籍: 1.1 Unit Test : 单元测试 - test the business logic in your app : 测试应用中的业务逻辑 1.2 UI Test : 界面测试 - test the UI of your app : 测试应用中的界面 1.3 测试书籍网址:《Testing Swift》 https://www.hackingwithswift.c…...

C++内存管理:其五、指针类型转换与嵌入式指针

一、内存池的缺陷 作者在上一版本里面介绍了链表实现内存池&#xff0c;其中有一个小缺陷&#xff1a;虽然较少了cookie的内存损耗&#xff0c;但是加入了一个额外的指针&#xff0c;仍然需要占用内存。我们仔细看内存池的设计思想&#xff0c;可以发现一个关键点&#xff1a;…...

常见锁的分类

入职体验&#xff1a; 今天运维岗位刚入职&#xff0c;但是目前还没有办理入职手续&#xff0c;但是领导发了一堆资料&#xff01;看了一下&#xff0c;非常多的新东西&#xff0c;只能说努力一把&#xff01;&#xff01;&#xff01; 一、锁的分类 1.1 可重入锁、不可重入锁…...

vue 鼠标划入划出多传一个参数

// item可以传递弹窗显示数据&#xff0c; $event相关参数可以用来做弹窗定位用 mouseover"handleMouseOver($event, item)" mouseleave"handleMouseLeave($event, item)"举个栗子&#xff1a; 做一个hover提示弹窗组件(用的vue3框架 less插件) 可以将组件…...

svn项目同步到gitLab

安装git 确保安装了git 新建一个文件夹svn-git 在文件夹中新建userinfo.txt文件&#xff0c;映射svn用户,这个文件主要是用于将SVN用户映射为Git用户&#xff08;昵称及其邮箱&#xff09;。 userinfo.txt具体格式如下&#xff1a; admin admin <admin163.com> lis…...

图解Dubbo,Dubbo 服务治理详解

目录 一、介绍1、介绍 Dubbo 服务治理的基本概念和重要性2、阐述 Dubbo 服务治理的实现方式和应用场景 二、Dubbo 服务治理的原理1、Dubbo 服务治理的架构设计2、Dubbo 服务治理的注册与发现机制3、Dubbo 服务治理的负载均衡算法 三、Dubbo 服务治理的实现方式1、基于 Docker 容…...

Css 如何取消a链接点击时的背景颜色

要取消 <a> 链接点击时的背景颜色&#xff0c;可以使用 CSS 的伪类 :active。你可以通过为 a:active 应用 background-color 属性设置为 transparent 或者 none&#xff0c;来取消点击时的背景色。下面是一个示例&#xff1a; a:active {background-color: transparent;…...

1.16.C++项目:仿muduo库实现并发服务器之HttpContext以及HttpServer模块的设计

文章目录 一、HttpContext模块二、HttpServer模块三、HttpContext模块实现思想&#xff08;一&#xff09;功能&#xff08;二&#xff09;意义&#xff08;三&#xff09;接口 四、HttpServer模块实现思想&#xff08;一&#xff09;功能&#xff08;二&#xff09;意义&#…...

ABAP 新增PO计划行时 新增行交货日期默认当前最大交期

ABAP 新增PO计划行时 新增行交货日期默认当前最大交期 DATA: ls_poitem TYPE mepoitem. DATA: ls_jhh TYPE meposchedule. DATA: ls_poitemc TYPE REF TO if_purchase_order_item_mm. DATA: is_persistent TYPE mmpur_bool. DATA: lt_eket TYPE TABLE OF eket. DATA: ls_e…...

VSCode怎么创建Java项目

首先安装好Java的开发环境&#xff1a;JDK在VSCode中安装适用于Java开发的插件。打开VSCode&#xff0c;点击左侧的扩展图标&#xff0c;搜索并安装Java Extension Pack插件。等待安装完成后&#xff0c;重启VSCode生效。创建一个新的Java项目&#xff0c;按下Ctrl Shift P&a…...

软件工程与计算(十四)详细设计中面向对象方法下的模块化

一.面向对象中的模块 1.类 模块化是消除软件复杂度的一个重要方法&#xff0c;每个代码片段相互独立&#xff0c;这样能够提高可维护性。在面向对象方法中&#xff0c;代码片段最重要的类&#xff0c;整个类的所有代码联合起来构成独立的代码片段。 模块化希望代码片段由两部…...

商城免费搭建之java商城 开源java电子商务Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…...

python教程:selenium WebDriver 中的几种等待

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 强制等待:sleep() import time sleep(5) #等待5秒设置固定休眠时间&#xff0c;单位为秒。 由python的time包提供, 导入 time 包后就可以使用。 缺点&#xff1a; 不智能&#xff0c;使用太多的sleep会影响脚本运行速度。…...

【MATLAB源码-第49期】基于蚁群算法(ACO)算法的栅格路径规划,输出最佳路径图和算法收敛曲线图。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 蚁群算法是一种模拟自然界蚂蚁觅食行为的启发式优化算法。在蚁群系统中&#xff0c;通过模拟蚂蚁之间通过信息素沟通的方式来寻找最短路径。 在栅格路径规划中&#xff0c;蚁群算法的基本步骤如下&#xff1a; 1. 初始化: …...

LabVIEW生产者消费者架构

LabVIEW生产者消费者架构 生产者/消费者模式可以轻松地同时处理多个进程&#xff0c;同时还能以不同速率迭代。 缓冲通信 当多个进程以不同速度运行时&#xff0c;就适合采用进程间缓冲通信。有了足够大的缓冲区后&#xff0c;生产者循环可以以快于消费者循环的速度运行&…...

成都瀚网科技:如何有效运营抖店来客呢?

随着电子商务的快速发展和移动互联网的普及&#xff0c;越来越多的企业开始将目光转向线上销售渠道。其中&#xff0c;抖音成为备受关注的平台。作为中国最大的短视频社交平台之一&#xff0c;抖音每天吸引数亿用户&#xff0c;这也为企业提供了巨大的商机。那么&#xff0c;如…...

iMazing2.17.3免费苹果手机备份还原助手

强大的 iOS 设备管理软件不管是 iPhone、iPad 或 iPod Touch 设备&#xff0c;只要将 iOS 设备连接到计算机&#xff0c;就可以处理不同类型的数据。iMazing 功能强大、易于使用&#xff0c;可以帮助您安全备份任何 iPhone、iPad 或 iPod Touch&#xff0c;备受用户信赖。 现在…...

sql查询到了数据但是实体类个别字段为null(映射失败)

参考博客&#xff1a; sql查询到了数据但是实体类个别字段为null(映射失败)_sql语句查到值,加字段!null没值-CSDN博客 问题描述&#xff1a; 1.SQL查询到了数据&#xff0c;在idea调试output控制台窗口打印出SQL语句&#xff0c;字段有值&#xff1b; 2.接收实体对象字段无…...

配置VScode开发环境-CUDA编程

如果觉得本篇文章对您的学习起到帮助作用&#xff0c;请 点赞 关注 评论 &#xff0c;留下您的足迹&#x1f4aa;&#x1f4aa;&#x1f4aa; 本文主要介绍VScode下的CUDA编程配置&#xff0c;因此记录以备日后查看&#xff0c;同时&#xff0c;如果能够帮助到更多人&#xf…...

openGauss学习笔记-101 openGauss 数据库管理-管理数据库安全-客户端接入之用SSH隧道进行安全的TCP/IP连接

文章目录 openGauss学习笔记-101 openGauss 数据库管理-管理数据库安全-客户端接入之用SSH隧道进行安全的TCP/IP连接101.1 背景信息101.2 前提条件101.3 操作步骤 openGauss学习笔记-101 openGauss 数据库管理-管理数据库安全-客户端接入之用SSH隧道进行安全的TCP/IP连接 101.…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...