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)}
}

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

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

相关文章

论文阅读之《Kindling the Darkness: A Practical Low-light Image Enhancer》

目录 摘要 介绍 已有方法回顾 普通方法 基于亮度的方法 基于深度学习的方法 基于图像去噪的方法 提出的方法 2.1 Layer Decomposition Net 2.2 Reflectance Restoration Net 2.3 Illumination Adjustment Net 实验结果 总结 Kindling the Darkness: A Practical L…

在线课堂知识付费积分兑换小程序源码系统 带完整搭建教程

大家好啊&#xff0c;今天罗峰来给大家分享一个在线课堂知识付费积分兑换小程序源码系统&#xff0c;以下是部分功能实现核心代码图&#xff1a; 系统特色功能一览&#xff1a; 积分获取&#xff1a;用户可以通过在平台上的各种操作&#xff0c;例如观看直播课程、学习文章、完…

塑料透光率测试可测试塑料部件的透明度和纯度

随着电子设备的快速发展&#xff0c;尤其是智能手机、平板电脑、可穿戴设备等新兴产品的普及&#xff0c;对塑料材料的需求量也在逐渐增加。因为这些电子设备需要大量的塑料材料来制造外壳、内部结构、部件等。电子设备在塑料行业的发展迅速&#xff0c;推动了塑料材料的技术进…

苹果手机怎么恢复数据?推荐这款数据恢复软件!

苹果手机一直以高颜值、系统稳定&#xff0c;以及优质的用户体验而闻名&#xff0c;这也使得购买苹果手机的用户逐渐增多。在手机中我们会保存各种各样的数据&#xff0c;包括照片、视频、备忘录、聊天记录等等。但是&#xff0c;这些数据可能会因为某些原因而导致丢失。 那么…

如何转换Corona和Vray材质?cr材质转vr材质的方法

cr材质转vr材质的方法一&#xff1a;使用CG Magic插件&#xff0c;一键转换 CG Magic是一款基于3ds Max深度开发的智能化辅助插件&#xff0c;上千项实用功能&#xff0c;降低渲染时长&#xff0c;节省时间和精力&#xff0c;大幅简化工作流程&#xff0c;助力高效完成创作。 …

Day3力扣打卡

打卡记录 改变一个整数能得到的最大差值&#xff08;贪心&#xff09; 链接 得到最大的整数&#xff0c;找到一个高位将它修改为 9。同理&#xff0c;想要得到最小的整数&#xff0c;找到一个高位将它修改为 0。 class Solution { public:int maxDiff(int num) {auto replace …

5种常见的软件缺陷分析方法

软件缺陷分析方法对于软件开发非常重要&#xff0c;能够帮助团队识别和分析软件中的缺陷问题&#xff0c;从而制定相应的解决方案&#xff0c;并持续改进软件质量和可靠性。通过合理应用这些方法&#xff0c;可以大幅提高软件开发效率和质量。 软件开发过程中&#xff0c;可能存…

Mysql 内外链接,索引,事务,用户管理以及用C语言链接Mysql

文章目录 内外链接索引索引的相关操作全文索引 事务事务的操作事务的隔离级别隔离级别3个记录隐藏列字段 用户管理权限修改 使用C语言链接数据库 内外链接 两张表直接做笛卡尔积为内连接&#xff0c;之前使用的都是内连接 两张表&#xff1a;stu和exam 将两张表进行连接&…

1、Flowable基础

Flowable是BPMN的一个基于java的软件实现&#xff0c;不过Flowable不仅仅包括BPMN&#xff0c;还有DMN决策表和CMMN Case管理引擎&#xff0c;并且有自己的用户管理、微服务API等一系列功能&#xff0c;是一个服务平台。 官方手册&#xff1a;https://tkjohn.github.io/flowab…

推荐系统离线评估方法和评估指标,以及在推荐服务器内部实现A/B测试和解决A/B测试资源紧张的方法。还介绍了如何在TensorFlow中进行模型离线评估实践。

文章目录 &#x1f31f; 离线评估&#xff1a;常用的推荐系统离线评估方法有哪些&#xff1f;&#x1f34a; 1. RMSE/MSE&#x1f34a; 2. MAE&#x1f34a; 3. Precision/Recall/F1-score&#x1f34a; 4. Coverage&#x1f34a; 5. Personalization&#x1f34a; 6. AUC &…

Spring Security登录账户自定义与数据持久化(5)

1、用户自定义 在前面的案例中&#xff0c;我们的登录用户是基于配置文件来配置的(本质是基于内存)&#xff0c;但是在实际开发中&#xff0c;这种方式肯定是不可取的&#xff0c;在实际项目中&#xff0c;用户信息肯定要存入数据库之中。 Spring Security支持多种用户定义方…

和鲸ModelWhale与中科可控X系列异构加速服务器完成适配认证,搭载海光芯片,构筑AI算力底座

AIGC 时代&#xff0c;算力作为新型生产力&#xff0c;是国家和企业构建竞争优势的关键。而随着传统计算方式无法满足新时代激增的算力需求&#xff0c;计算场景的多元化和计算应用的复杂化推动了 CPUGPU 异构平台的加速组建。在此全球激烈角逐的大趋势下&#xff0c;我国信创产…

《论文阅读28》OGMM

一、论文 研究领域&#xff1a; 点云配准 | 有监督 部分重叠论文&#xff1a;Overlap-guided Gaussian Mixture Models for Point Cloud Registration WACV 2023 二、概述 概率3D点云配准方法在克服噪声、异常值和密度变化方面表现出有竞争力的性能。本文将点云对的配准问题…

腾讯云服务器带宽下载速度表(附上行带宽计算方法)

腾讯云服务器公网带宽下载速度计算&#xff0c;1M公网带宽下载速度是128KB/秒&#xff0c;5M带宽下载速度是512KB/s&#xff0c;腾讯云10M带宽下载速度是1.25M/秒&#xff0c;腾讯云百科txybk.com来详细说下腾讯云服务器不同公网带宽实际下载速度以及对应的上传速度对照表&…

凉鞋的 Unity 笔记 202. 变量概述与简介

202. 变量概述与简介 想要用好变量不是一件简单的事情&#xff0c;因为变量需要命名。 我们可以从两个角度看待一个变量&#xff0c;第一个角度是变量的功能&#xff0c;第二个是变量的可读性。 变量的功能其实非常简单&#xff0c;变量可以存储一个值&#xff0c;这个值是特…

Flume 简介及基本使用

1.Flume简介 Apache Flume 是一个分布式,高可用的数据收集系统。它可以从不同的数据源收集数据,经过聚合后发送到存储系统中,通常用于日志数据的收集。Flume 分为 NG 和 OG (1.0 之前) 两个版本,NG 在 OG 的基础上进行了完全的重构,是目前使用最为广泛的版本。下面的介绍均…

创建node、vue、以及@vuecli 和 vue-cli 的区别

创建node、vue、以及vue/cli 和 vue-cli 的区别 创建vue的五种方法 参考 如何创建一个vue项目&#xff08;详细步骤&#xff09; 方法一&#xff1a;vue init webpack 项目名&#xff08;vue-cli2.x的初始化方式&#xff09; vue init webpack blog 创建项目(blog 是项目名…

疯狂堆料!技嘉钛雕Z790 AORUS PRO X主板图赏

技嘉推出了钛雕Z790 AORUS PRO X主板。 现在这款新品已经来到了我们评测室&#xff0c;下面为大家带来图赏。 技嘉钛雕Z790 AORUS PRO X主板采用新一代超耐久显卡插槽&#xff0c;约58KG承重能力、内衬保护显卡PCB。 其采用1812相供电设计&#xff0c;4根双通道DDR5内存插槽&am…

开源情报之领英人脸情报收集,如何快速收集上亿张人脸情报

一.前言 先看应用例子&#xff1a; 残忍至极&#xff01;乌克兰用人脸识别战死俄军&#xff0c;联系母亲打“心理战” 情报机构&#xff0c;所掌握的数据&#xff0c;可以是市面上流出的任何数据&#xff0c;比如市面上泄露的领英数据&#xff0c;facebook&#xff0c;twitter&…

Kylin麒麟系统下安装人大金仓

虚拟机在线安装 install open-vm-tools-desktop -y 简要介绍 人大金仓数据库管理系统KingbaseES&#xff08;简称&#xff1a;金仓数据库或KingbaseES&#xff09;是北京人大金仓信息技术股份有限公司自主研制开发的具有自主知识产权的通用关系型数据库管理系统。金仓数据库主…