CUnit详解(基于linux下的白盒单元测试)

2023-11-07

CUnit是一个对C语言编写的程序进行单元测试的框架,在线文档说它作为一个静态链接库被链接到用户的测试代码中。

它提供了一种简洁的框架来建立测试架构,并提供丰富的断言(Assertion)来测试通用数据类型。除此之外,它还提供了

许多不同的结构来运行测试用例和报告测试结果。

(1)CUnit的架构

可以看出Cunit也是有组织的,主要分几个角色,Registry,Suite及Test方法。可以通过下面例子,体会到这种组织关系。
按官方文档说明,使用Cunit的主要步骤有:
1) Write functions for tests (and suite init/cleanup if necessary).
2) Initialize the test registry - CU_initialize_registry()
3) Add suites to the test registry - CU_add_suite()
4) Add tests to the suites - CU_add_test()
5) Run tests using an appropriate interface, e.g. CU_console_run_tests
6) Cleanup the test registry - CU_cleanup_registry

(2)测试模式

下面是四种测试模式:
1 Automated Output to xml file            Non-interactive
2 Basic      Flexible programming        interface Non-interactive 
3 Console    Console interface (ansi C)     Interactive 
4 Curses     Graphical interface (Unix)     Interactive
第一种模式是将结果输出到XML文档中,便于生成报告。第二种模式是每一次运行结束之后在standard output中显示测试结果,不能保留测试结果数据。第三种模式是console方式的,可以人机交互;前两种模式是非交互式的。第四种只在Unix中使用。

(3)测试的基本流程
1)编写单元测试函数(有必要的话要写suite的init/cleanup函数)。Write functions for tests (and suite init/cleanup if necessary).
2)调用函数CU_initialize_registry()初始化测试注册单元(Test Registry)。 Initialize the test registry - CU_initialize_registry()
3)调用函数CU_add_suite() 将测试包(suite)添加到测试注册单元(Test Registry)中。Add suites to the test registry - CU_add_suite()
4)调用函数CU_add_test()将测试用例添加到测试包(suite)中。Add tests to the suites - CU_add_test()
5)使用合适的接口来运行测试用例。Run tests using an appropriate interface, e.g. CU_console_run_tests
6)调用函数CU_cleanup_registry清除测试注册单元(Test Registry)。Cleanup the test registry - CU_cleanup_registry()

先编写一个具体两个简单功能的函数,然后写Testcase来测试它。

文件主要有:
1) strformat.h :字符串功能函数的接口文件
2)strformat.c :字符串功能函数的实现
3)testcase.c : 测试用例及Cunit运行环境
4)makefile :

直接上代码吧,strformat.h

#ifndef _strformat_h
#define _strformat_h

typedef char * string;
 
int string_lenth(string word);
string to_Upper(string word);

string add_str(string word1 ,string word2);

#endif

strformat.c

#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include "strformat.h"


/**************************************************************************
函数名称:字符串相加
**************************************************************************/
string add_str(string word1 ,string word2){
    return (strcat(word1, word2));
}

/**************************************************************************
函数名称:将字符串转换成大写格式
**************************************************************************/
string to_Upper(string word){
    int i;
    for(i = 0;word[i] !='\0' ;i++){
        if(word[i]<'z' && word[i]>'a'){
            word[i] -= 32;
        }
    }
    return word;
    
}

/**************************************************************************
函数名称:字符串长度
**************************************************************************/
int string_lenth(string word){
    int i;
    for(i = 0 ;word[i] != '\0';i++){
        
    }
    return i;
}

testcase.c

/* testcase.c --- 
 * 
 * Filename: testcase.c
 * Description: 测试实例 
 */

/* Commentary:
 * 当前文件用来定义测试方法,suite,及registry信息,若测试方法有变化,只需要修改当前文件即可。
 * 第一步:书写测试函数的代码,建议以"test_"为前缀。
 * 第二步:将测试方法归类,即将相似功能的测试方法放到一个数组里,以便把它们指定给一个suite
 * 第三步:创建suite,可按功能或模块,生成多个test suite,
 * 第四步:书写测试方法的总调用方法,AddTests(),用来统一启动测试方法。
 */

/* Code: */
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>

#include <CUnit/Basic.h>
#include <CUnit/Console.h>
#include <CUnit/CUnit.h>
#include <CUnit/TestDB.h>
#include "strformat.h"

/**************************************************************************
函数名称:测试string_lenth()方法
**************************************************************************/
void test_string_lenth(void){
    string test = "Hello";
    int len = string_lenth(test);
    CU_ASSERT_EQUAL(len,5);
}

/**************************************************************************
函数名称:测试方法to_Upper()
**************************************************************************/

void test_to_Upper(void){
    char test[] = "Hello";
    CU_ASSERT_STRING_EQUAL(to_Upper(test),"HELLO");
}

/**************************************************************************
函数名称:测试方法 add_str()
**************************************************************************/
void test_add_str(void){
    char test1[] = "Hello!";
    char test2[] = "MGC";
    CU_ASSERT_STRING_EQUAL(add_str(test1,test2),"Hello!MGC");
}

/**************************************************************************
数组名称:将多个测试方法打包成组,以供指定给一个Suite
功能描述:每个suite可以有一个或多个测试方法,以CU_TestInfo数组形式指定
**************************************************************************/
// CU_TestInfo是Cunit内置的一个结构体,它包括测试方法及描述信息
CU_TestInfo testcase[] = {
    {"test_for_lenth:",test_string_lenth    },
    {"test_for_add:",test_add_str    },
    CU_TEST_INFO_NULL
};

CU_TestInfo testcase2[] = {
    {"test for Upper :",test_to_Upper    },
    CU_TEST_INFO_NULL
};

/**************************************************************************
函数名称:suite初始化过程
功能描述:
输入参数:
返   回:
**************************************************************************/
int suite_success_init(void){
    return 0;
}

/**************************************************************************
函数名称:suite清理过程,以便恢复原状,使结果不影响到下次运行
**************************************************************************/
int suite_success_clean(void){
    return 0;
}

//定义suite数组,包括多个suite,每个suite又会包括若干个测试方法。
CU_SuiteInfo suites[] = {
    {"testSuite1",suite_success_init,suite_success_clean,testcase},
    {"testsuite2",suite_success_init,suite_success_clean,testcase2},
    CU_SUITE_INFO_NULL
};

/**************************************************************************
函数名称:测试类的调用总接口
**************************************************************************/
void AddTests(){
    assert(NULL != CU_get_registry());
    assert(!CU_is_test_running());

    if(CUE_SUCCESS != CU_register_suites(suites)){
        exit(EXIT_FAILURE);
    }
}
/*************************************************************************
*功能描述:运行测试入口
**************************************************************************/
int RunTest(){
        if(CU_initialize_registry()){
                fprintf(stderr, " Initialization of Test Registry failed. ");
                exit(EXIT_FAILURE);
        }else{
                AddTests();
                /**** Automated Mode *****************
                CU_set_output_filename("TestMax");
                CU_list_tests_to_file();
                CU_automated_run_tests();
                //************************************/
                
                /***** Basice Mode *******************
                CU_basic_set_mode(CU_BRM_VERBOSE);
                CU_basic_run_tests();
                //************************************/

                /*****Console Mode ********************
                CU_console_run_tests();
                //************************************/

                CU_cleanup_registry();
                return CU_get_error();
        }
}
/*************************************************************************
*功能描述:测试类主方法
**************************************************************************/

int main(int argc, char * argv[])
{
   return  RunTest();
    
}

代码:makefile

IINC=-I/usr/local/include/CUnit
LIB=-L/usr/local/lib/

all:  strformat.c testcase.c
    gcc -o test $(INC) $(LIB)  $^ -lcunit -static

注:
1)Cunit安装很简单,从官方地址上下载源代码后,在本机依次执行
./configure
make 
sudo make install
安装成功后相关的库及头文件安装到默认路径下。编译时添加选项:
-I/usr/local/include/CUnit
-L/usr/local/lib/
就如makefile中的一样。

下面我们欣赏一下Cunit的常见几种运行模式
1)Automated Mode
先将testcase.c中156~159代码放开注释,此时便是以automated模式运行,此模块没有交互能力,直接生成XML格式的报表,先make,然后运行后,在当前目录下生成两个报表
TestMax-Listing.xml和TestMax-Results.xml(前者是测试用例的列表,后者是测试用例的测试结果) ,但这两个文件是不能直接观看的,要查看这两个文件,需要使用如下xsl和dtd文件:CUnit-List.dtd和CUnit-List.xsl用于解析列表文件, CUnit-Run.dtd和CUnit-Run.xsl用于解析结果文件。这四个文件在CUnit包里面有提供,安装之后在$(PREFIX) /share/CUnit目录下,默认安装的话在/home/lirui/local/share/CUnit目录下。在查看结果之前,需要把这六 个文件:TestMax-Listing.xml, TestMax-Results.xml, CUnit-List.dtd, CUnit-List.xsl, CUnit-Run.dtd, CUnit-Run.xsl拷贝到一个目录下,然后用浏览器打开两个结果的xml文件就可以了。
如下图所示:

 

 

2) Console Mode
在testcase.c中将其它模式代码注释掉,放开168行代码,便转换成Console模式了。console模式支持交互,如支持运行,查看错误等操作,如下图所示:

从上图即可看出,输入R来运行,输入F来查看错误用例,输入Q来退出

这种模式在实际中是很实用的。

3)Basic Mode
在testcase.c中将其它模式的代码注释掉,放到163~164行代码,便转换成Basic模式,这种是不支持交互的,直接打印出运行结果。

可以看出,这种模式也是比较简单快捷的


2.在两种不同环境下使用CUnit来上面的例子进行单元测试。

2.1 在Windows XP下,在VC 6.0 集成CUnit来进行单元测试。
(1)自己动手生成链接静态库CUnit.lib。
下载CUnit-2.1-0-src.zip,解压,在CUnit-2.1-0/CUnit目录下,用VC 6.0打开工程文件CUnit.dsp,有个提示,说没有找到workspace文件,不会理会,直接确定。然后在当前打开的工程项目中,点击"FileView",展开文件树形结构,任意点击一个文件打开,然后在最上面的工具栏点击“编译”和“链接”,在CUnit-2.1-0/CUnit目录下就生产CUnit.lib。
(2)在VC 6.0新建一个名为"Test_CUit"的Win32 console application工程,将上面例子中的文件包含进来。
(3)下载CUnit-2.1-0-winlib.zip,解压,把解压的目录CUnit-2.1-0复制到当前的工程目录下。
(4)将CUnit.lib叶复制到当前的工程目录下,并在"Project"->"Settings..."->"Link"->"Object/library modules"中内容的末尾增加CUnit.lib,用空格和前面的静态库文件隔开,然后点击"OK"即可。
(5)在"Test_CUit"工程项目中,在最上面的工具栏点击“编译”->“链接”->“运行”,就可以看到控制台界面。输入相应的操作符号进行对应的操作,不再详述。

备注:在TestMainModule.c的AddTestMainModule()函数中注释掉的部分是第一种测试模式"Automated Output to xml file",默认的模式是第三种控制台模式。把控制台模式注释掉,而把第一种测试模式打开,则运行时会在当前目录下三个XML文件:CUnit-Memory-Dump.xml,TestMax-Listing.xml,TestMax-Results.xml。将这三个文件复制到目录CUnit-2.1-0/share/CUnit下,然后用浏览器打开后两个XML文件,可以看到测试报告的结果。

2.2 在Linux下,利用CUnit来进行单元测试。
1.编译CUnit,编译后,头文件目录在/root/local/include/CUnit中,静态库文件在/root/local/lib/下。
(1)用root用户登录,下载CUnit-2.1-0-src.tar.gz。
(2)tar -zxvf CUnit-2.1-0-src.tar.gz
(3)cd CUnit-2.1-0
(4)./configure --prefix=$HOME/local
(5)make
(6)make install
2.编写一个Makefile文件,放入到在源文件目录中,内容如下:

  1. INC=-I/root/local/include  
  2. LIB=-L/root/local/lib  
  3.   
  4. all: MainModule.c TestMainModule.c CUnitRunTest.c  
  5.     gcc $^ -o test $(INC) $(LIB) -lcunit -lcurses -static  
  6. clean:  
  7.     rm -rf test  
3.在源文件目录下执行make命令即可。

4.运行./test即可看见console命令界面。


3.关于断言的使用
CUnit提供了一系列的断言来测试逻辑条件,这些断言的成功或是失败的结果都由CUnit单元测试框架跟踪,并在单元测试结束后可以看到。每个断言测试一个逻辑条件。如果选择"XXX_FATAL"这些断言,意味着断言失败后单元测试用例不再继续执行,所以带"FATAL"的断言版本需要谨慎使用。断言被包含在"CUnit/CUnit.h"这个头文件中声明的。现在就从CUnit的文档说明中摘录它的断言声明。

CU_ASSERT(int expression)
CU_ASSERT_FATAL(int expression)
CU_TEST(int expression)
CU_TEST_FATAL(int expression)
Assert that expression is TRUE (non-zero)
CU_ASSERT_TRUE(value)
CU_ASSERT_TRUE_FATAL(value)
Assert that value is TRUE (non-zero)
CU_ASSERT_FALSE(value)
CU_ASSERT_FALSE_FATAL(value)
Assert that value is FALSE (zero)
CU_ASSERT_EQUAL(actual, expected)
CU_ASSERT_EQUAL_FATAL(actual, expected)
Assert that actual = = expected
CU_ASSERT_NOT_EQUAL(actual, expected))
CU_ASSERT_NOT_EQUAL_FATAL(actual, expected)
Assert that actual != expected
CU_ASSERT_PTR_EQUAL(actual, expected)
CU_ASSERT_PTR_EQUAL_FATAL(actual, expected)
Assert that pointers actual = = expected
CU_ASSERT_PTR_NOT_EQUAL(actual, expected)
CU_ASSERT_PTR_NOT_EQUAL_FATAL(actual, expected)
Assert that pointers actual != expected
CU_ASSERT_PTR_NULL(value)
CU_ASSERT_PTR_NULL_FATAL(value)
Assert that pointer value == NULL
CU_ASSERT_PTR_NOT_NULL(value)
CU_ASSERT_PTR_NOT_NULL_FATAL(value)
Assert that pointer value != NULL
CU_ASSERT_STRING_EQUAL(actual, expected)
CU_ASSERT_STRING_EQUAL_FATAL(actual, expected)
Assert that strings actual and expected are equivalent
CU_ASSERT_STRING_NOT_EQUAL(actual, expected)
CU_ASSERT_STRING_NOT_EQUAL_FATAL(actual, expected)
Assert that strings actual and expected differ
CU_ASSERT_NSTRING_EQUAL(actual, expected, count)
CU_ASSERT_NSTRING_EQUAL_FATAL(actual, expected, count)
Assert that 1st count chars of actual and expected are the same
CU_ASSERT_NSTRING_NOT_EQUAL(actual, expected, count)
CU_ASSERT_NSTRING_NOT_EQUAL_FATAL(actual, expected, count)
Assert that 1st count chars of actual and expected differ
CU_ASSERT_DOUBLE_EQUAL(actual, expected, granularity)
CU_ASSERT_DOUBLE_EQUAL_FATAL(actual, expected, granularity)
Assert that |actual - expected| <= |granularity|
Math library must be linked in for this assertion.
CU_ASSERT_DOUBLE_NOT_EQUAL(actual, expected, granularity)
CU_ASSERT_DOUBLE_NOT_EQUAL_FATAL(actual, expected, granularity)
Assert that |actual - expected| > |granularity|
Math library must be linked in for this assertion.
CU_PASS(message) Register a passing assertion with the specified message. No logical test is performed.
CU_FAIL(message)
CU_FAIL_FATAL(message)
Register a failed assertion with the specified message. No logical test is performed

 

给出两个版本的源代码供下载。注:在VC6.0下面的源文件不能直接在Linux下使用,如果要用,则提示每个源文件的末尾都要加一个换行符。

【1】VC 6.0 的例子

【2】 Linux的例子(无法上传.tar.gz格式的文件)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CUnit详解(基于linux下的白盒单元测试) 的相关文章

  • C# SmtpClient编程中如何设置带有中文的附件文件名?

    我的代码如下 ContentType ct new ContentType ct MediaType MediaTypeNames Application Octet ct Name 这是一个很长的中文文件名希望能用它在附件名中 Doc A
  • 格式说明符%02x

    我有一个简单的程序 include
  • C#.Net 邮件将进入垃圾邮件文件夹

    我正在从 ASP net Web 应用程序发送电子邮件 邮件发送成功 没有失败 但大多数都进入了垃圾邮件文件夹 请帮助我克服垃圾邮件过滤器 我的发送邮件代码 public void SendMail string FromAddress s
  • C# 中一次性对象克隆会导致内存泄漏吗?

    检查这个代码 class someclass IDisposable private Bitmap imageObject public void ImageCrop int X int Y int W int H imageObject
  • 混合模型优先和代码优先

    我们使用模型优先方法创建了一个 Web 应用程序 一名新开发人员进入该项目 并使用代码优先方法 使用数据库文件 创建了一个新的自定义模型 这 这是代码第一个数据库上下文 namespace WVITDB DAL public class D
  • MVC 5 中具有 ASP.NET Identity 的 Autofac 不会验证 OWIN 管道中的安全标记

    我在 MVC 5 中设置了 AutoFac 来与 ASP NET Identity 一起使用 表面上一切似乎都工作正常 即用户可以创建帐户并登录 但后来我发现 当安全标记更改时 用户不会注销 通过在 AspNetUsers 表中进行暴力破解
  • Makefile 和 .Mak 文件 + CodeBlocks 和 VStudio

    我对整个 makefile 概念有点陌生 所以我对此有一些疑问 我正在 Linux 中使用 CodeBlocks 创建一个项目 我使用一个名为 cbp2mak 的工具从 CodeBlocks 项目创建一个 make 文件 如果有人知道更好的
  • JavaScript 错误:MVC2 视图中的条件编译已关闭

    我试图在 MVC2 视图页面中单击时调用 JavaScript 函数 a href Select a JavaScript 函数 function SelectBenefit id code alert id alert code 这里 b
  • C# 根据当前日期传递日期时间值

    我正在尝试根据 sql server 中的两个日期获取记录 Select from table where CreatedDate between StartDate and EndDate我通过了5 12 2010 and 5 12 20
  • OpenGL:如何检查用户是否支持glGenBuffers()?

    我检查了文档 它说 OpenGL 版本必须至少为 1 5 才能制作glGenBuffers 工作 用户使用的是1 5版本但是函数调用会导致崩溃 这是文档中的错误 还是用户的驱动程序问题 我正在用这个glGenBuffers 对于VBO 我如
  • Unity手游触摸动作不扎实

    我的代码中有一种 错误 我只是找不到它发生的原因以及如何修复它 我是统一的初学者 甚至是统一的手机游戏的初学者 我使用触摸让玩家从一侧移动到另一侧 但问题是我希望玩家在手指从一侧滑动到另一侧时能够平滑移动 但我的代码还会将玩家移动到您点击的
  • Linux 上的 RTLD_LOCAL 和dynamic_cast

    我们有一个由应用程序中的一些共享库构成的插件 我们需要在应用程序运行时更新它 出于性能原因 我们在卸载旧插件之前加载并开始使用新插件 并且只有当所有线程都使用旧插件完成后 我们才卸载它 由于新插件和旧插件的库具有相同的符号 我们dlopen
  • 如何防止 Blazor NavLink 组件的默认导航

    从 Blazor 3 1 Preview 2 开始 应该可以防止默认导航行为 https devblogs microsoft com aspnet asp net core updates in net core 3 1 preview
  • ASP.NET Core 中间件与过滤器

    在阅读了 ASP NET Core 中间件之后 我对何时应该使用过滤器以及何时应该使用中间件感到困惑 因为它们似乎实现了相同的目标 什么时候应该使用中间件而不是过滤器 9频道有一个关于此的视频 ASP NET 怪物 91 中间件与过滤器 h
  • .NET 和 Mono 之间的开发差异

    我正在研究 Mono 和 NET C 将来当项目开发时我们需要在 Linux 服务器上运行代码 此时我一直在研究 ASP NET MVC 和 Mono 我运行 Ubuntu 发行版 想要开发 Web 应用程序 其他一些开发人员使用 Wind
  • 使用 gcc 时在头文件中查找定义的好方法是什么?

    在使用 gcc 时 有人有推荐的方法在头文件中查找定义吗 使用 MSVC 时 我只需右键单击并选择 转到定义 这非常好 我使用过 netbeans gcc 它确实有代码帮助 包括到定义的超链接 所以这是一种选择 但是 我想知道是否有任何其他
  • 调用 .ToArray() 时出现 ArgumentException

    我有一个经常被清除的列表 代码完全是这样的 VisitorAgent toPersist List
  • 构建 C# MVC 5 站点时项目之间的处理器架构不匹配

    我收到的错误如下 2017 年 4 月 20 日构建 13 23 38 C Windows Microsoft NET Framework v4 0 30319 Microsoft Common targets 1605 5 警告 MSB3
  • Fedora dnf 更新不起作用?

    当我尝试使用 update 命令更新 Fedora 22 时 sudo dnf update 我收到以下错误 错误 无法同步存储库 更新 的缓存 无法准备内部镜像列表 Curl 错误 6 无法解析主机名 无法解析主机 mirrors fed
  • 如何为有时异步的操作创建和实现接口

    假设我有数百个类 它们使用 计算 方法实现公共接口 一些类将执行异步 例如读取文件 而实现相同接口的其他类将执行同步代码 例如将两个数字相加 为了维护和性能 对此进行编码的好方法是什么 到目前为止我读到的帖子总是建议将异步 等待方法冒泡给调

随机推荐

  • 弹性计算

    弹性计算包括云服务器 云数据库 负载均衡 云服务器 整合了高性能服务器与优质网络资源 云OS统一管理集群资源 每个集群可虚拟出多个独立服务器 且可以在集群中自由迁移 数据存储在云OS 大大提高云服务器的稳定性 关系型数据库服务 一个基于高稳
  • Hex文件和bin文件以及flash大小关系

    Program Size Code 31128 RO data 6572 RW data 52 ZI data 1852 keil软件编译后会出现上面的提示 其意义如下 Code 指程序中代码的字节数 RO data 指程序中定义的常量字节
  • Oceanbase列传

    Oceanbase列传 分布式与存储技术 跳至内容 首页 关于郁白 文章列表 文章预告 正在追越狱第五季 两阶段提交的工程实践 两阶段提交 2 Phase Commit简称2PC 协议是用于在多个节点之间达成一致的通信协议 它是实现 有状态
  • 1000元一根的Type C数据线

    转自 https zhuanlan zhihu com p 179946944 苹果官方商城近日上架了一根数据线 官方名称 雷雳 3 Pro 售价 949 元 看到价格 我脑海中的第一反应是 谁会买这根近千元的数据线 是贫穷限制了我的想象力
  • spring boot自动装配之@EnableAutoConfiguration详解

    1 EnableAutoConfiguration作用 EnableAutoConfiguration用于类或接口上 在spring boot中注解位于 SpringBootApplication注解上 SpringBootConfigur
  • 【数据结构1】数据结构的基本概念

    数据结构的基本概念 数据 数据是信息的载体 是描述客观事物属性的数 字符及所有能输入到计算机中并被计算机程序识别和处理的符号的集合 数据是计算机程序加工的原料 数据元素 数据项 数据元素是数据的基本单位 通常作为一个整体进行考虑和处理 一个
  • x = x.view(x.size(0), -1) 的理解

    之前对于pytorch的网络编程学习都是大致理解每一层的概念 有些语法语句没有从原理上弄清楚 就比如标题的x x view x size 0 1 这句话一般出现在model类的forward函数中 具体位置一般都是在调用分类器之前 分类器是
  • LogisticRegressionCV 参数使用以及含义 笔记

    第一次接触LogisticRegressionCV 记录一下 Logistic回归是分类算法 不能应用于回归中 传入模型的y值 不能是float类型 必须是int类型 正则化选择参数 penalty gt L1 L2 默认是L2的正则化 一
  • 【MySQL】MySQL高手是如何练成的?

    MySQL 什么是MySQL呢 怎样练成MySQL高手 在Linux安装MySQL 问题处理 Mysql 的用户管理 什么是MySQL呢 Mysql 是开源的 可以定制的 采用了 GPL 协议 可以根据业务需要修改源码来开发自己的 Mysq
  • 2023 年为您的网站提供 30 个免费的 CSS 加载动画

    我们将使用 Lottie 文件 Lottie 文件 毫不费力地为网络 应用程序 社交和设计带来最小的 免费的 随时可用的动态图形 立即创建 编辑 测试 协作和发布 Lottie 动画 脚步 1 在你的html中添加这个脚本 2 我们将提供一
  • MySQL基于复制线程实现MTS并行恢复binlog

    文章目录 一 MySQL备份恢复流程 二 并行恢复binlog原理 三 操作步骤 四 总结 一 MySQL备份恢复流程 MySQL数据恢复通常分为两个步骤 恢复全备数据 MySQL有多种备份工具 分为物理备份和逻辑备份 具体可以参看下面这篇
  • 因果推断--双重差分法(DID)的原理和实际应用(一)

    目录 一 应用场景 二 DID知识介绍 2 1 理论知识介绍 2 2 DID图形化解释 三 应用案例 3 1 构造对照组 3 2 平行趋势检验 3 3 因果效应评估 四 优缺点总结 一 应用场景 在精细化运营场景中 常常会面临如下问题 不方
  • 关闭谷歌浏览器开发者工具中的 chrome-extension 网络请求

    在谷歌浏览器的设置里 选择扩展程序 关闭插件 即可 ps 得自己一个一个的关闭试试
  • 绝不要不做点评,除非你想站队或被站队

    在项目中 对任何一方提供的任何材料 包括会议纪要 周报 月报 函件 项目技术文档及过程文档中等 绝不要直接通过 一定要提出一些意见 哪怕很微不足道的意见 原因 1 如果直接通过 意味着你同意 即你和文件提供方站在同一立场 2 如果提出一些意
  • React和Vue的区别

    文章目录 React与Vue的相同点 1 都支持服务器渲染 2 都数据驱动视图 3 都遵循组件化的思想 4 都使用虚拟DOM 5 都有状态管理 React与Vue框架的不同点 1 框架本质不同 2 数据流不同 3 监听数据变化的实现原理不同
  • Python项目命令行执行无法找到Module(ModuleNotFoundError)

    缘起 在IDE中可以执行的Python代码 直接在命令行则无法执行 错误信息提示 ModuleNotFoundError No module named xxxxx 原因分析 基于命令行执行的时候 当前项目的代码没有作为依赖包放入命令行的依
  • 电力电子转战数字IC——路科MCDF全览(持续更新)

    经过两次面试后 对MCDF做一次全面的深入总结 目前进度 硬件部分的node fifo 寄存器 formatter MCDF顶层 APB接口 TB接口 软件部分的chnl pkg fmt pkg apb pkg mcdf rgm pkg m
  • VMware 虚拟机图文安装和配置 AlmaLinux OS 8.6 教程

    镜像下载 域名解析 时间同步请点击 阿里云开源镜像站 一 VMWare 安装配置 1 VMware 下载地址 VMware Workstation Pro 16 x 需要登录 安装和配置步骤略 二 AlmaLinux OS 8 6 安装配置
  • 从客户端发送到服务器的请求包括哪些信息,客户端发送消息给服务器

    客户端发送消息给服务器 内容精选 换一换 VR云渲游平台提供了设备的实时监控功能 您可以通过监控大屏 查看指定设备在云上运行时的实时监控数据 当设备处于 运行中 状态时 才可以查看设备的实时监控数据 当设备与云服务器正确连接时 可在设备列表
  • CUnit详解(基于linux下的白盒单元测试)

    CUnit是一个对C语言编写的程序进行单元测试的框架 在线文档说它作为一个静态链接库被链接到用户的测试代码中 它提供了一种简洁的框架来建立测试架构 并提供丰富的断言 Assertion 来测试通用数据类型 除此之外 它还提供了 许多不同的结