【C#生态园】提升C#开发效率:掌握这六款单元测试利器
从xUnit到SpecFlow:C#测试驱动开发全指南
前言
在C#开发中,单元测试和模拟框架是至关重要的工具,它们可以帮助开发人员确保代码的质量和可靠性。本文将介绍一些常用的C#单元测试框架和相关库,包括xUnit、NUnit、Moq、FluentAssertions、AutoFixture和SpecFlow,探讨它们的核心功能、使用场景、安装配置以及API概览,帮助读者更好地了解和选择合适的工具来进行测试驱动开发。
欢迎订阅专栏:C#生态园
文章目录
- 从xUnit到SpecFlow:C#测试驱动开发全指南
- 前言
- 1. xUnit:一个用于C#的单元测试框架
- 1.1 简介
- 1.1.1 核心功能
- 1.1.2 使用场景
- 1.2 安装与配置
- 1.2.1 安装指南
- 1.2.2 基本配置
- 1.3 API 概览
- 1.3.1 测试方法
- 1.3.2 断言
- 2. NUnit:一个用于C#的单元测试框架
- 2.1 简介
- 2.1.1 核心功能
- 2.1.2 使用场景
- 2.2 安装与配置
- 2.2.1 安装指南
- 2.2.2 基本配置
- 2.3 API 概览
- 2.3.1 测试方法
- 2.3.2 断言
- 3. Moq:一个用于C#的模拟框架
- 3.1 简介
- 3.1.1 核心功能
- 3.1.2 使用场景
- 3.2 安装与配置
- 3.2.1 安装指南
- 3.2.2 基本配置
- 3.3 API 概览
- 3.3.1 模拟对象
- 3.3.2 验证方法
- 4. FluentAssertions:一个用于C#的断言库
- 4.1 简介
- 4.1.1 核心功能
- 4.1.2 使用场景
- 4.2 安装与配置
- 4.2.1 安装指南
- 4.2.2 基本配置
- 4.3 API 概览
- 4.3.1 断言方法
- 4.3.2 自定义断言
- 5. AutoFixture:一个用于C#的测试数据生成库
- 5.1 简介
- 5.1.1 核心功能
- 5.1.2 使用场景
- 5.2 安装与配置
- 5.2.1 安装指南
- 5.2.2 基本配置
- 5.3 API 概览
- 5.3.1 数据生成
- 5.3.2 自定义生成
- 6. SpecFlow:一个用于C#的行为驱动开发框架
- 6.1 简介
- 6.1.1 核心功能
- 6.1.2 使用场景
- 6.2 安装与配置
- 6.2.1 安装指南
- 6.2.2 基本配置
- 6.3 API 概览
- 6.3.1 特性文件
- 6.3.2 步骤定义
- 总结
1. xUnit:一个用于C#的单元测试框架
xUnit 是一个用于 C# 的单元测试框架,它提供了丰富的功能来帮助开发者编写和执行单元测试。
1.1 简介
1.1.1 核心功能
xUnit 支持各种单元测试相关的功能,包括断言、参数化测试、跳过测试等。它还提供了丰富的插件扩展机制,可以满足不同项目的需求。
1.1.2 使用场景
xUnit 最适合于 C# 项目的单元测试,无论是小型项目还是大型项目,它都能够满足测试的需要。
1.2 安装与配置
1.2.1 安装指南
使用 NuGet 包管理器可以很方便地安装 xUnit,只需在 Visual Studio 中搜索并安装 xUnit
即可。
PM> Install-Package xunit
1.2.2 基本配置
安装完成后,需要创建一个测试项目,并引用 xUnit 相关的命名空间,如 Xunit
和 Xunit.Assert
。
1.3 API 概览
1.3.1 测试方法
可以使用 Fact
特性定义一个测试方法,并在其中编写测试逻辑。
using Xunit;public class MyTestClass
{[Fact]public void TestMethod(){// 测试逻辑}
}
更多关于测试方法的信息,请参阅 xUnit 官方文档。
1.3.2 断言
xUnit 提供了丰富的断言方法,可以用于验证测试的预期结果是否符合预期。
using Xunit;
using Xunit.Assert;public class MyTestClass
{[Fact]public void TestMethod(){var result = SomeMethod(); // 假设 SomeMethod 返回值为 42Assert.Equal(42, result);}
}
更多关于断言的信息,请参阅 xUnit 断言文档。
2. NUnit:一个用于C#的单元测试框架
2.1 简介
NUnit 是一个用于 C# 的单元测试框架,它提供了丰富的功能和灵活的 API,可以帮助开发人员编写可靠的单元测试。
2.1.1 核心功能
NUnit 提供了丰富的断言方法、参数化测试、数据驱动测试等功能,同时支持并行测试执行和测试运行的生命周期管理。
2.1.2 使用场景
NUnit 常用于 C# 项目的单元测试,通过编写测试用例来验证代码的正确性和稳定性。
2.2 安装与配置
2.2.1 安装指南
安装 NUnit 可以通过 NuGet 包管理器,在 Visual Studio 中创建 C# 项目后,打开 NuGet 包管理器控制台,执行以下命令进行安装:
Install-Package NUnit
Install-Package NUnit3TestAdapter
2.2.2 基本配置
配置 NUnit 可以在项目中添加 NUnit 测试类,并使用相应的属性和断言方法来编写测试逻辑。
2.3 API 概览
2.3.1 测试方法
NUnit 中的测试方法使用 [Test]
属性标记,可以通过 [SetUp]
和 [TearDown]
属性标记初始化和清理方法。
using NUnit.Framework;[TestFixture]
public class MyTests
{[SetUp]public void Setup(){// 初始化操作}[TearDown]public void TearDown(){// 清理操作}[Test]public void TestMethod(){// 测试逻辑}
}
更多关于测试方法的信息,请参考NUnit官方文档。
2.3.2 断言
NUnit 提供了丰富的断言方法,如 Assert.AreEqual()
, Assert.IsTrue()
, Assert.Throws()
等,用于验证测试结果是否符合预期。
[Test]
public void TestAdd()
{Calculator calculator = new Calculator();int result = calculator.Add(2, 3);Assert.AreEqual(5, result);
}
更多关于断言的信息,请参考NUnit官方文档。
3. Moq:一个用于C#的模拟框架
Moq是一个流行的用于C#的模拟框架,它允许开发人员创建模拟对象以进行单元测试。
3.1 简介
Moq的核心功能包括:
3.1.1 核心功能
- 创建模拟对象
- 设置对象的行为和属性
- 验证对象的方法是否被调用
3.1.2 使用场景
Moq通常在C#的单元测试中使用,用于模拟那些不容易构造或者引发副作用的对象,比如数据库访问、外部接口调用等。
3.2 安装与配置
使用Moq前,首先需要安装该库并进行基本配置。
3.2.1 安装指南
可以通过NuGet包管理器来安装Moq。在Visual Studio中,右击项目,在“管理NuGet程序包”中搜索Moq并安装即可。
3.2.2 基本配置
安装完毕后,在测试文件的顶部添加以下引用:
using Moq;
3.3 API 概览
Moq提供了丰富的API,主要包括以下两个方面:
3.3.1 模拟对象
使用Moq可以轻松地创建模拟对象。下面是一个简单的示例,假设有一个名为IFoo
的接口,我们希望为它创建一个模拟对象并设置其行为:
// 创建模拟对象
var mock = new Mock<IFoo>();// 设置模拟对象的行为
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);// 使用模拟对象
bool result = mock.Object.DoSomething("ping");
更多关于模拟对象的信息,可以参考Moq官方文档。
3.3.2 验证方法
Moq还支持验证模拟对象的方法是否被调用。以下是一个示例,假设我们想要验证DoSomething
方法是否被调用过:
// 创建模拟对象
var mock = new Mock<IFoo>();// 使用模拟对象
mock.Object.DoSomething("ping");// 验证方法是否被调用
mock.Verify(foo => foo.DoSomething("ping"), Times.Once());
更多关于验证方法的信息,可以参考Moq官方文档。
4. FluentAssertions:一个用于C#的断言库
FluentAssertions 是一个流畅的断言库,用于 C# 测试。它提供了一种更具可读性和表达力的方式来编写测试断言。
4.1 简介
FluentAssertions 提供了丰富的断言方法以及定制化的断言能力,使得测试代码更易于编写和维护。其核心功能包括:
4.1.1 核心功能
- 提供流畅的断言语法,使断言更易读、易懂
- 支持对对象、集合、异常等进行全面的断言
- 提供自定义断言的扩展能力
4.1.2 使用场景
FluentAssertions 可以在各种 C# 测试框架中使用,如 NUnit、xUnit 和 MSTest。它适用于单元测试、集成测试和端到端测试等场景。
4.2 安装与配置
4.2.1 安装指南
可以通过 NuGet 包管理器或 .NET CLI 来安装 FluentAssertions:
Install-Package FluentAssertions
或者使用 .NET CLI:
dotnet add package FluentAssertions
4.2.2 基本配置
在测试项目中,只需引入 FluentAssertions
命名空间即可开始使用该库。示例代码如下:
using FluentAssertions;
4.3 API 概览
4.3.1 断言方法
FluentAssertions 提供了丰富的断言方法,涵盖了各种常见的测试断言需求。例如,在进行对象属性断言时,可以使用以下代码:
var person = new Person("Alice", 30);
person.Name.Should().Be("Alice");
person.Age.Should().BeGreaterThan(20);
更多断言方法的详细信息,请参考官方文档。
4.3.2 自定义断言
除了内置的断言方法外,FluentAssertions 还支持自定义断言,在特定业务场景下能够提供更灵活的断言能力。以下是一个简单的自定义断言示例:
public class CustomAssertions
{public static void BePositive(int value){value.Should().BeGreaterThan(0);}
}
在测试代码中使用自定义断言:
CustomAssertions.BePositive(5);
欲了解更多关于自定义断言的内容,请参考官方文档。
5. AutoFixture:一个用于C#的测试数据生成库
AutoFixture 是一个用于 .NET 平台的开源库,它可以帮助我们快速、灵活地生成测试数据。在进行单元测试或集成测试时,经常需要创建各种类型的测试对象,而 AutoFixture 可以简化这个过程,使得我们能够更专注地撰写测试逻辑,而不用花费大量时间来构建测试数据。
5.1 简介
AutoFixture 的核心功能是自动生成符合我们要求的测试数据,并注入到我们的测试对象中。它可以帮助我们轻松应对各种复杂的数据需求,如引用类型、值类型、集合类型等,而无需手动编写大量重复的测试数据初始化代码。
5.1.1 核心功能
AutoFixture 的核心功能包括:
- 自动生成符合要求的测试数据
- 支持对测试数据进行定制和扩展
- 灵活而强大的 API 接口
5.1.2 使用场景
AutoFixture 适用于任何需要测试数据的场景,特别是在进行单元测试时,可以显著提高测试数据准备的效率。
5.2 安装与配置
5.2.1 安装指南
您可以通过 NuGet 包管理器来安装 AutoFixture。在 Visual Studio 中,打开包管理控制台并执行以下命令:
Install-Package AutoFixture
5.2.2 基本配置
在使用 AutoFixture 之前,通常需要为其进行一些基本的配置。例如,可以通过 Fixture 实例来进行配置,也可以通过 AutoDataAttribute 来自动执行配置。
5.3 API 概览
5.3.1 数据生成
AutoFixture 提供了多种方式来生成测试数据。下面是一个简单的示例,演示了如何使用 AutoFixture 生成一个字符串类型的测试数据:
var fixture = new Fixture();
string testString = fixture.Create<string>();
Console.WriteLine(testString);
在这个示例中,我们创建了一个 Fixture 实例,然后调用其 Create 方法来生成一个字符串类型的测试数据,并将其输出到控制台。
5.3.2 自定义生成
除了默认的数据生成规则外,AutoFixture 还支持我们根据需要自定义数据生成规则。例如,我们可以为特定类型自定义生成规则,以满足特定的测试需求。以下示例展示了如何自定义生成一个 DateTime 类型的测试数据:
var fixture = new Fixture();
fixture.Customize<DateTime>(c => c.FromFactory(() => DateTime.Now.AddDays(-7)));
DateTime testDate = fixture.Create<DateTime>();
Console.WriteLine(testDate);
在上述示例中,我们为 DateTime 类型设置了一个自定义的生成规则,使其生成的日期为当前日期往前推 7 天的日期。
以上就是 AutoFixture 库的简单介绍以及安装配置方法和 API 概览,更多详细信息可以参考 AutoFixture 官方网站。
6. SpecFlow:一个用于C#的行为驱动开发框架
6.1 简介
SpecFlow 是一个支持行为驱动开发(BDD)的工具,它使得使用 Gherkin 语言编写规范和自然语言测试变得更加容易。通过将业务需求、开发和测试紧密结合,SpecFlow 可以帮助团队更好地沟通,并促进软件质量的提升。
6.1.1 核心功能
- 支持 Gherkin 语言
- 自然语言表示测试场景
- 将自然语言转换为可执行的测试代码
- 支持与多种 .NET 测试框架集成
6.1.2 使用场景
- 适用于需要将业务需求和测试用例进行关联的项目
- 适合需要提高测试代码可读性和可维护性的团队
- 对于希望在敏捷开发中实现更好的业务沟通和自动化测试的团队
6.2 安装与配置
6.2.1 安装指南
可以通过 NuGet 安装 SpecFlow:
Install-Package SpecFlow
更多安装详情请参考 SpecFlow 官方文档
6.2.2 基本配置
在 Visual Studio 中创建一个新的 SpecFlow 项目后,需要配置 SpecFlow 运行环境。在 App.config
文件中添加以下配置:
<configSections><section name="specFlow" type="TechTalk.SpecFlow.Configuration.ConfigurationSectionHandler, TechTalk.SpecFlow" />
</configSections>
<specFlow><unitTestProvider name="MsTest" />
</specFlow>
更多配置选项请参考 SpecFlow 配置文档
6.3 API 概览
6.3.1 特性文件
特性文件使用 Gherkin 语言编写,以 .feature
结尾。例如:
Feature: LoginAs a registered userI want to be able to login with my credentialsSo that I can access the applicationScenario: Successful loginGiven I am on the login pageWhen I enter valid username and passwordThen I should be redirected to the dashboard
更多特性文件编写规范请参考 Gherkin 文档
6.3.2 步骤定义
步骤定义是将 Gherkin 语言转换为可执行代码的地方。例如,对应上面特性文件的步骤定义可能如下:
[Binding]
public class LoginSteps
{[Given(@"I am on the login page")]public void GivenIAmOnTheLoginPage(){// Step implementation}[When(@"I enter valid username and password")]public void WhenIEnterValidUsernameAndPassword(){// Step implementation}[Then(@"I should be redirected to the dashboard")]public void ThenIShouldBeRedirectedToTheDashboard(){// Step implementation}
}
更多步骤定义规范请参考 SpecFlow 步骤定义文档
以上是 SpecFlow 的简介、安装配置和 API 概览部分,希望对你有所帮助。
总结
本文对C#中常用的单元测试框架和相关库进行了全面介绍和分析,涵盖了xUnit、NUnit、Moq、FluentAssertions、AutoFixture和SpecFlow等六个工具。通过阐述它们的核心功能、使用场景、安装配置和API概览,读者可以更好地了解这些工具的特点和优势,从而为自己的项目选择合适的工具进行单元测试和行为驱动开发。
相关文章:
【C#生态园】提升C#开发效率:掌握这六款单元测试利器
从xUnit到SpecFlow:C#测试驱动开发全指南 前言 在C#开发中,单元测试和模拟框架是至关重要的工具,它们可以帮助开发人员确保代码的质量和可靠性。本文将介绍一些常用的C#单元测试框架和相关库,包括xUnit、NUnit、Moq、FluentAsse…...

【QT】自制一个简单的小闹钟,能够实现语音播报功能
做了一个自制的小闹钟,能够自己输入时间,以及对应的闹铃,时间到了自动播放设定的闹铃,可以随时取消重新设定,采用分文件编译 注意:需要在.pro文件中加入:QT core gui texttospeech 代码…...
基于深度学习的图像描述生成
基于深度学习的图像描述生成(Image Captioning)是一种将计算机视觉与自然语言处理结合的任务,其目标是通过自动生成自然语言来描述输入的图像。该技术能够理解图像中的视觉内容,并生成相应的文本描述,广泛应用于视觉问…...

Linux和C语言(Day11)
一、学习内容 讲解有参函数 形参 和 实参 形参——定义时的参数,形式上的参数,没有实际意义,语法上必须带有数据类型 void fun(int a,int b); void fun(int a[],int n); void fun(char *s); 可以是:变量、数组、指针 实参——调用…...
使用Zlib库进行多文件或者多文件夹的压缩解压缩
zlib库可在git上自己clone下来然后使用cmake工具生成解决方案,编译、生成zlib二进制文件。然后将zlib库引入项目: //zlib库支持 #include "../zlib/include/zlib.h" #ifdef _DEBUG #pragma comment(lib, "../zlib/lib/zlibd.lib") …...

CSGHub携手Nvidia NIM、阿里计算巢打造企业级私有化部署解决方案
强强联合 人工智能与大数据的迅速发展,大模型的推理应用和资产管理已成为企业数字化转型的重要组成部分,企业正寻求高效、安全的AI模型部署解决方案。为应对日益增长的计算需求和复杂的数据管理挑战,CSGHub、Nvidia和阿里云计算巢强强联手&a…...
opencv的球面投影
cv::detail::SphericalProjector 在全景图像拼接任务中,可能需要对多个图像进行球面投影以实现无缝拼接。每个cv::detail::SphericalProjector可以负责一个图像的球面投影操作。通过将多个这样的投影器存储在std::vector中,可以对一组图像依次进行投影处…...
5. 去中心化应用(dApp)
去中心化应用(dApp) 去中心化应用(dApp)是基于区块链技术构建的应用程序,其核心特性是去中心化、透明和开放。dApp与传统应用有许多显著的区别,它们在实现和功能上都带来了新的变革。以下是对dApp的详细介…...

k8s服务发布Ingress
Kubernetes暴露服务的方式目前只有三种:LoadBlancer Service、NodePort Service、Ingress,通俗来讲,ingress和之前提到的Service、Deployment,也是一个k8s的资源类型,ingress用于实现用域名的方式访问k8s内部应用。 In…...

区块链学习笔记1--比特币
区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。 从狭义上来说:区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式数据结构,并以密码学的方式保证的不可篡改和不可伪造的分布式账本。 意思就是…...
在 Vite 项目中自动为每个 Vue 文件导入 base.less
在 Vue.js 项目中,使用 Less 作为 CSS 预处理器时,我们通常会创建一个全局的样式文件(如 base.less),用于存放一些全局变量、混合、通用样式等。为了避免在每个 Vue 组件中手动导入这个文件,我们可以通过配…...
RUST 学习之全局变量
RUST 全局变量 rust 全局变量编译期初始化的全局变量静态常量静态变量原子类型的静态变量 运行期初始化的全局变量lazy_staticBox::leakOnceCell & OnceLock 参考文档 rust 全局变量 编译期初始化的全局变量 静态常量 在编译期初始化,所以其赋值只能是表达式…...
代码随想录八股训练营第三十九天| C++
前言 一、说一下 lambda函数? 1.1.Lambda 函数的一般语法如下: 1.2.捕获子句: 二、C 怎么实现一个单例模式? 2.1.懒汉式(线程不安全): 2.2.饿汉式(线程安全): 2.3.双重检查锁定ÿ…...

服务网关工作原理,如何获取用户真实IP?
文章目录 一、什么是网关二、网关工作原理 (★)三、SpringCloud Gateway3.1 Gateway 简介3.2 Gateway 环境搭建3.3 自定义路由规则 (★)3.4 局部过滤器3.5 全局过滤器(案例:获取用户真实IP地址) (★) 补充1:不同类型的客户端如何设…...

单链表的实现(C语言)
目录 1.单链表 1.1 实现单链表 1.1.1 文件创建 1.1.2 链表功能了解 1.1.3 链表的结点 1.1.4 链表的函数声明 1.1.5 链表功能的实现 链表是一种链式结构,物理结构不连续,逻辑结构是连续的,在计算机中链表的实际存储是按照一个结点内存放…...

sql语句的训练2024/9/9
1题 需要看清思路:不是将数据库中的device_id的名字改为user_infors_example,而是在查找的时候,需要将device_id看成user_infors_example来进行查找。 答案 select device_id AS user_infos_example FROM user_profile limit 2 2 当固定查找…...

【QT】常用控件-下
欢迎来到Cefler的博客😁 🕌博客主页:折纸花满衣 🏠个人专栏:QT 目录 👉🏻QComboBox👉🏻 QSpinBox👉🏻QDateTimeEdit👉🏻QD…...

828华为云征文|华为云Flexus X实例docker部署Jitsi构建属于自己的音视频会议系统
828华为云征文|华为云Flexus X实例docker部署Jitsi构建属于自己的音视频会议系统 华为云最近正在举办828 B2B企业节,Flexus X实例的促销力度非常大,特别适合那些对算力性能有高要求的小伙伴。如果你有自建MySQL、Redis、Nginx等服务的需求&a…...

25虾皮笔试shopee笔试测评sea笔试测评题型
虾皮笔试shopee笔试测评用的自己的笔试系统,全英文笔试: 1.Numerical Reasoning Test:10题,言语推断和数学计算 2. Verbal Reasoning Test:10题,言语理解,每题一段英文材料,选对错…...

启明云端乐鑫代理商,乐鑫ESP32无线芯片方案,物联网设备WiFi联动控制
随着智能和远程技术的飞速发展,物联网(IoT)逐渐出现在我们生活的每一个角落。乐鑫以其创新的无线通信技术,正成为智能家居、工业自动化和医疗设备等领域的推动者。 无线WiFi芯片模组不仅提供了强大的数据处理能力,还赋予了设备以直观的交互方…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...