实践 Fake ClientSet 单元测试

简介: 在 Kubernetes 相关的开发中,client-go 是最常用的,对于 client-go 相关的代码我们可以通过 fake ClientSet 来编写单元测试,本文将实践利用 fake ClientSet

目录

什么是 ClientSet

实践环节


什么是 ClientSet

ClientSet顾名思义,就是一堆 Client 的集合。

在 client-go 中,ClientSet 声明了对于 Kubernetes 内置资源的操作接口的集合,代码位于 kubernetes/client-go


Fake ClientSet 顾名思义就是 “假” 的 Client 集合,实现了 ClientSet的接口,可以对 client-go 的代码进行模拟操作,可直接用于业务代码的单元测试,代码在 kubneretes/client-go 中。


实践环节

接下来我们将实际操作一下常见的几种 fake clientset 的用法


我们构造一个简单的场景,比如我们在业务逻辑中需要对 Node 进行更新标签的操作,逻辑如下:

import (
"context"metav1"k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes")
funcLabelNode(ctxcontext.Context, cskubernetes.Interface, nodeNamestring, labelsmap[string]string) error {
node, err :=cs.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{})
iferr!=nil {
returnerr    }
for_, l :=rangelabels {
node.Labels[l] =labels[l]
    }
_, err=cs.CoreV1().Nodes().Update(ctx, node, metav1.UpdateOptions{})
iferr!=nil {
returnerr    }
returnnil}


其中 kubernetes.Interface 就是 ClientSet实现的标准接口,比如常见的通过 ~/.kube/config加载 restConfig 再创建 ClientSet,得到的ClientSet就实现了 kubernetes.Interface

rc, err :=clientcmd.BuildConfigFromFlags("", "~/.kube/config")
iferr!=nil {
panic(err)
}
cs, err :=kubernetes.NewForConfig(rc)
iferr!=nil {
panic(err)
}


接下来我们编写上述逻辑的单元测试,首先我们先来看一下完整的代码

提示:

这里只做简单单元测试的演示,并不涉及到单元测试结构的合理性

packagenodesimport (
"testing""reflect""context"corev1"k8s.io/api/core/v1"metav1"k8s.io/apimachinery/pkg/apis/meta/v1"fakeclientset"k8s.io/client-go/kubernetes/fake")
funcTest_LabelNode(t*testing.T) {
cs :=fakeclientset.NewSimpleClientset(&corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "fake-node-1",
Labels: map[string]string{
"fake.label.kubernetes.io": "fake",
   },
    },
 })
newLabels :=map[string]string{
"fake.label.kubernetes.io": "new-value",
 }
err :=LabelNode(context.Background(), cs, "fake-node-1", newLabels)
iferr!=nil {
t.Error(err)
return }
got, err :=cs.CoreV1().Nodes().Get(context.Background(), "fake-node-1", metav1.GetOptions{})
iferr!=nil {
t.Error(err)
return }
if!reflect.DeepEqual(got.Labels, newLabels) {
t.Error(err)
return }
}


可以通过 NewSimpleClientset来生成 fake clientSet,这里的入参是 objects ...runtime.Object,其中 runtime.Object接口是 Kubernetes 资源都会实现的接口,也就是我们需要传入期望可以进行 CRUD 的假资源对象列表。


提示:

这里 runtime.Object不仅限于内置资源外,自定义资源也可以

cs :=fakeclientset.NewSimpleClientset(&corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "fake-node-1",
Labels: map[string]string{
"fake.label.kubernetes.io": "fake",
        },
    },
})


获取到 ClientSet后,我们可以将 Client 作为入参传入到逻辑中,并且按照业务逻辑传入需要更新的 Labels

newLabels :=map[string]string{
"fake.label.kubernetes.io": "new-value",
}
err :=LabelNode(context.Background(), cs, "fake-node-1", newLabels)
iferr!=nil {
t.Error(err)
return}

此时我们再通过这个 ClientSet去调用,获取的资源就是经过逻辑处理后的了,通过 reflect.DeepEqual 进行比较。

同样的,如果我们在处理逻辑中对初始化时传入的资源进行了 Delete等操作,资源同样会被销毁掉。


在我们对 Kubernetes 资源的操作中,fakeClient 有些逻辑操作是无法实现的,比如对于 fieldSelector 的筛选,是不支持的,详细可以参考这个 isuue:https://github.com/kubernetes/kubernetes/issues/78824


如下逻辑中,如果对 DeploymentList 通过 fakeClient 进行过滤,无法生效, labelSelector 是可以的。

// parse field selectordefaultSelector := []string{
fmt.Sprintf("metadata.namespace!=%s", metav1.NamespaceDefault),
fmt.Sprintf("metadata.namespace!=%s", metav1.NamespaceSystem),
}
fieldSelector, err :=fields.ParseSelector(strings.Join(defaultSelector, ","))
iferr!=nil {
returnnil, nil, err}
options.FieldSelector=fieldSelector.String()
deployList, err :=d.cs.AppsV1().Deployments(metav1.NamespaceNone).List(context.Background(), options)
iferr!=nil {
returnnil, nil, err}


除了上述我们提到的NewSimpleClientset,快速创建一个 FakeClient,还可以通过添加 AddReactor 来对 action 进行判断,增加更详细的判断逻辑, 比如如下案例:

cs :=&fakeclientset.Clientset{}
cs.AddReactor("*", "deployments", func(actionclientgotesting.Action) (handledbool, retruntime.Object, errerror) {
returntrue, &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name:      name,
Namespace: namespace,
        },
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "busybox",
                },
            },
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": "busybox",
                    },
                },
Spec: corev1.PodSpec{
Containers: []corev1.Container{
                        {
Name:  "container-1",
Image: "busybox",
                        },
                    },
                },
            },
        },
    }, nil})


相关链接:

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
10月前
|
数据采集 监控 机器人
浅谈网页端IM技术及相关测试方法实践(包括WebSocket性能测试)
最开始转转的客服系统体系如IM、工单以及机器人等都是使用第三方的产品。但第三方产品对于转转的业务,以及客服的效率等都产生了诸多限制,所以我们决定自研替换第三方系统。下面主要分享一下网页端IM技术及相关测试方法,我们先从了解IM系统和WebSocket开始。
217 4
|
2月前
|
机器学习/深度学习 自然语言处理 API
query改写:大模型应用测试离不开的实践
queryrewrite 是一个用于大模型应用测试的 Python 库,专注于查询(query)的改写与验证。它支持多种改写方法,包括大型语言模型(LLM)、词汇表替换和同义词替换,同时提供多种验证方法如 ROUGE-L、BLEU、帕累托最优和LLM语义相似度,以确保改写后的查询在语义上保持一致。该项目特别优化了对中文文本的处理,涵盖分词和相似度计算。用户可通过 pip 安装,并支持扩展不同的 LLM 模型,如 OpenAI、Ollama 等。
523 87
query改写:大模型应用测试离不开的实践
|
2月前
|
JSON 自然语言处理 算法
大模型应用测试必备技能:问题对生成实践
本文介绍了利用LangChain的QAGenerationChain从文本生成问题-答案对(QA pairs)的方法,旨在解决LLM应用开发中测试数据生成的格式不统一、库版本过时、模型输出异常及代码可维护性差等问题。文中提供了完整的代码实现,并对生成结果进行了有效性评估,包括语义相似度检查、关键词匹配和重复性检测,确保生成的QA对质量可靠,适用于知识库测试与评估。
301 86
|
25天前
|
Java 测试技术 API
自动化测试工具集成及实践
自动化测试用例的覆盖度及关键点最佳实践、自动化测试工具、集成方法、自动化脚本编写等(兼容多语言(Java、Python、Go、C++、C#等)、多框架(Spring、React、Vue等))
69 6
|
25天前
|
人工智能 边缘计算 搜索推荐
AI产品测试学习路径全解析:从业务场景到代码实践
本文深入解析AI测试的核心技能与学习路径,涵盖业务理解、模型指标计算与性能测试三大阶段,助力掌握分类、推荐系统、计算机视觉等多场景测试方法,提升AI产品质量保障能力。
|
1月前
|
人工智能 自然语言处理 测试技术
AI测试平台的用例管理实践:写得清晰,管得高效,执行更智能
在测试过程中,用例分散、步骤模糊、回归测试效率低等问题常困扰团队。霍格沃兹测试开发学社推出的AI测试平台,打通“用例编写—集中管理—智能执行”全流程,提升测试效率与覆盖率。平台支持标准化用例编写、统一管理操作及智能执行,助力测试团队高效协作,释放更多精力优化测试策略。目前平台已开放内测,欢迎试用体验!
|
2月前
|
人工智能 资源调度 jenkins
精准化回归测试:大厂实践与技术落地解析
在高频迭代时代,全量回归测试成本高、效率低,常导致关键 bug 漏测。精准化测试通过代码变更影响分析,智能筛选高价值用例,显著提升测试效率与缺陷捕获率,实现降本增效。已被阿里、京东、腾讯等大厂成功落地,成为质量保障的新趋势。
|
2月前
|
搜索推荐 Devops 测试技术
避免无效回归!基于MCP协议的精准测试影响分析实践
本文揭示传统测试的"孤岛困境",提出MCP(Model Context Protocol)测试新范式,通过模型抽象业务、上下文感知环境和协议规范协作,实现从机械执行到智能测试的转变。剖析MCP如何颠覆测试流程,展示典型应用场景,并提供团队落地实践路径,助力测试工程师把握质量效率革命的新机遇。
|
2月前
|
人工智能 缓存 自然语言处理
大模型性能测试完全指南:从原理到实践
本文介绍了大模型性能测试的核心价值与方法,涵盖流式响应机制、PD分离架构、五大关键指标(如首Token延迟、吐字率等),并通过实战演示如何使用Locust进行压力测试。同时探讨了多模态测试的挑战与优化方向,帮助测试工程师成长为AI系统性能的“诊断专家”。
|
4月前
|
人工智能 Java 测试技术
SpringBoot 测试实践:单元测试与集成测试
在 Spring Boot 测试中,@MockBean 用于创建完全模拟的 Bean,替代真实对象行为;而 @SpyBean 则用于部分模拟,保留未指定方法的真实实现。两者结合 Mockito 可灵活控制依赖行为,提升测试覆盖率。合理使用 @ContextConfiguration 和避免滥用 @SpringBootTest 可优化测试上下文加载速度,提高测试效率。
268 6

热门文章

最新文章