使用Kubernetes客戶端庫進行單元測試

2021-02-24 容器時代



如何對被 Kubernetes API 調用的代碼進行單元測試?

使用 Kubernetes 客戶端庫可以通過模擬集群來測試代碼。

作為在構建 kubernetes / minikube 時,第一批使用kubernetes / client-go 庫的用戶之一,我曾經詳盡的設計了服務、調度單元和部署來對我的代碼進行單元測試。現在,我發現有一種更簡單的方法可以用更少的代碼行來做同樣的事情。

我將演示如何測試一個列出了集群中運行的所有容器映像的簡單的函數。我建議你用 GKE 或 Docker 作為桌面,並且你還需要一個 Kubernetes 集群。

如果你想要運行命令並以交互方式繼續操作,請克隆示例倉庫 https://github.com/r2d4/k8s-unit-test-example 。

main.go>>>>

package main

import (
"github.com/pkg/errors"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/typed/core/v1"
)

// ListImages returns a list of container images running in the provided namespace
func ListImages(client v1.CoreV1Interface, namespace string) ([]string, error) {
pl, err := client.Pods(namespace).List(meta_v1.ListOptions{})
if err != nil {
return nil, errors.Wrap(err, "getting pods")
}

var images []string
for _, p := range pl.Items {
for _, c := range p.Spec.Containers {
images = append(images, c.Image)
}
}

return images, nil

}



我們可以從測試用例的定義開始,運行一些測試的框架代碼。

func TestListImages(t *testing.T) {

var tests = []struct {
description string
namespace string
expected []string
objs []runtime.Object
}{
{"no pods", "", nil, nil},
}

// Actual testing code goes here...

}

發生了什麼>>>>

這種編寫測試的風格稱為「表驅動測試」,是Go語言中首選的樣式,實際測試代碼會迭代表條目並執行必要的測試。測試代碼只需要寫一次,卻可以適用於每種情況。我門可以注意到一些有趣的事情:

測試用例的定義是用匿名結構保存的,因此我們可以簡潔的定義測試用例。

對象切片運行時,objs將保存我們的模擬 API 伺服器保存的所有正在運行的對象,此處我們選擇用一些調度單元來填充它,但其實可以在這裡使用任何 Kubernetes 對象。

如果測試用例非常瑣碎,伺服器上將沒有調度單元,並且不返回任何圖像。


讓我們來為每個測試用例都寫一段實際測試代碼。

for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
client := fake.NewSimpleClientset(test.objs...)
actual, err := ListImages(client.CoreV1(), test.namespace)
if err != nil {
t.Errorf("Unexpected error: %s", err)
return
}
if diff := cmp.Diff(actual, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
return
}
})
}

在這裡我們也可以注意到一些有趣的事情:

fake.NewSimpleClientset 返回一個使用提供的對象進行響應的客戶端集。它由一個非常簡單的對象跟蹤器支持,該跟蹤器按原樣處理創建、更新和刪除操作,而不應用任何驗證和默認值。

我們來創建一個調度單元助手函數,它將幫助我們提供一些測試的調度單元。由於我們關心的是命名空間和鏡像,所以我們可以創建一個可以基於這些參數創建新的調度單元的助手。

func pod(namespace, image string) *v1.Pod {
return &v1.Pod{ObjectMeta: meta_v1.ObjectMeta{Namespace: namespace}, Spec: v1.PodSpec{Containers: []v1.Container{{Image: image}}}}
}

我們來寫三個單元測試。第一個方法能確保我門獲取所有鏡像,這時我們需要使用特殊的命名空間值 「」 來列出命名空間中所有的調度單元。

{"all namespaces", "", []string{"a", "b"}, []runtime.Object{pod("correct-namespace", "a"), pod("wrong-namespace", "b")}}

第二種方法能確保我們按名稱空間正確篩選,忽略調度單元中的 wrong-namespace 。

{"filter namespace", "correct-namespace", []string{"a"}, []runtime.Object{pod("correct-namespace", "a"), pod("wrong-namespace", "b")}}

第三種方法能確保如果所需的命名空間中沒有調度單元,則不會返回任何內容。

{"wrong namespace", "correct-namespace", nil, []runtime.Object{pod("wrong-namespace", "b")}}

把上面這些代碼放在一起。

func TestListImages(t *testing.T) {
var tests = []struct {
description string
namespace string
expected []string
objs []runtime.Object
}{
{"no pods", "", nil, nil},
{"all namespaces", "", []string{"a", "b"}, []runtime.Object{pod("correct-namespace", "a"), pod("wrong-namespace", "b")}},
{"filter namespace", "correct-namespace", []string{"a"}, []runtime.Object{pod("correct-namespace", "a"), pod("wrong-namespace", "b")}},
{"wrong namespace", "correct-namespace", nil, []runtime.Object{pod("wrong-namespace", "b")}},
}

for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
client := fake.NewSimpleClientset(test.objs...)
actual, err := ListImages(client.CoreV1(), test.namespace)
if err != nil {
t.Errorf("Unexpected error: %s", err)
return
}
if diff := cmp.Diff(actual, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
return
}
})
}

}

上一篇:Kubernetes 源碼分析之 kubelet(四)




長按掃描二維碼,添加管理員微信

加入容器時代交流群吧~

記得備註「加群」字樣哦



相關焦點

  • 使用testify和mockery庫簡化單元測試
    ,簡單介紹了 testing 庫的使用方法。後來發現 testify/require 和 testify/assert 可以大大簡化單元測試的寫法,完全可以替代 t.Fatalf 和 t.Errorf,而且代碼實現更為簡短、優雅。再後來,發現了 mockery 庫,它可以為 Go interface 生成一個 mocks struct。
  • 使用MockMVC進行Controller單元測試
    這個測試套件就可以使用Spring-test庫中的MockMVC了。接下來,將以查詢接口為例,介紹如何對該接口進行單元測試。首先,和普通的基於Mockito單元測試一樣,通過@Mock註解來對這個Service進行mock,並通過@InjectMocks註解實現注入。
  • Jenkins上集成JUnit和TestLink進行Java單元測試流程與配置
    ,即如果是首次使用Testlink,需要首先根據Testlink的使用文檔進行測試項目->測試計劃->測試用例的完整創建後再進行此Jenkins平臺的集成。/testlink(如:http://localhost/testlink)Jenkins:http://localhost:80802部署過程基於Eclipse工程進行Junit單元測試如果使用eclipse 開發,其內部集成了Junit jar包,我們只需要引入即可選中項目右鍵執行Build->Add Library,在彈出的界面選擇
  • 使用Gitlab CI對Kubernetes上的應用進行JUnit測試
    ,而且也是必要的,我相信很多讀者已經在做軟體測試了。首先,定義完整的上下文:因為我們所有的應用都在Kubernetes上,所以只涵蓋了相關基礎設施上的測試。我們用werf構建和部署圖片(相當於Helm自然而然地參與到流水線中)。我不會介紹測試本身的一些細節:我們的測試主要在客戶端實現,我們只需要確保其(合併請求中存在相應的報告)正常運行即可。
  • 使用Kubernetes進行容器編排
    它是集群的主要控制單元,將接受管理員或DevOps團隊發出的命令,然後將它們轉發到底層節點。主節點(master)可以配置成在單個機器上運行,在高可用性集群中主節點也可以配置成在多個機器上運行。這是為了確保集群的容錯能力並降低停機的可能性。節點就是執行主伺服器分配的任務的機器。節點有時被稱為Worker或Minion。圖1.
  • 如何使用Kubernetes GPU集群自動化深度學習訓練?
    客戶端為了控制你的集群,如從客戶端控制 master,你需要對客戶端的正確用戶進行認證。該指南中並沒有為客戶端創建一個單獨的用戶,我們只是從 master 節點複製用戶。在客戶端安裝 kubectl。我只在 mac 上測試過,但應該也適用 linux。我不知道是否適用於 windows,但又有誰關心 windows 呢。Mac
  • Kubernetes 使用 Keycloak 進行認證
    在初始狀態下,Keycloak 服務使用的是非安全協議(HTTP),但是Kubernetes 要求和 Auth Server 之間的通訊必須使用 TLS,這裡要使用keycloak來為Kubernetes進行認證,必須開啟HTTPS,請提前在 Keycloak 中配置好,要注意如果使用 docker 部署,docker 的默認埠是8443.
  • Android單元測試的簡單使用
    網上的單元測試教程都特別深奧或者千篇一律,像我這種小白看完之後也是摸不著頭腦,也不知道該如何下手,所以我就寫了這篇簡單的Android單元測試教程,也算是拋磚引玉。hl=zh-cn#test-types  測試前的準備  首先要在 moudle-name下的build.gradle文件裡面引入相關的依賴:  (只貼出了和測試相關的)  其中Espresso是Google官方提供並推薦使用的測試庫。
  • 使用Kubernetes、K3s和Traefik2進行本地開發
    由於我並不經常需要外部集群,因此我使用輕量級K3s發行版來進行Kubernetes本地開發。K3s是為IoT和邊緣計算而構建的經過認證的Kubernetes發行版之一,還能夠按產品規模部署到VM。我使用K3s的方式是這樣的:在我的工作筆記本上本地安裝K3s,儘管有時我需要在本地部署較重的測試工作負載,為此,我準備了兩個神器——兩個運行ESXi的外部Intel NUCs。
  • Operator概述: 如何對 Kubernetes 進行擴展
    kubernate 擴展如上圖所示,從客戶端到底層容器運行時,絕大部分地方 Kubernetes 都為我們預留了擴展點,我們從上往下一個一個的來看1. kubectlkubectl 是我們平時和 Kubernetes 交互使用的最多的客戶端工具,常見的運維操作都會通過
  • 我到底應該使用哪個 CRI 替換 kubernetes 集群的 Docker?
    那麼除了 docker 之外,我們還可以使用其他什麼 CRI 呢?下面是我已經測試的幾個 CRI,並進行一些基準測試來對他們進行了簡單的對比,希望對你有所幫助:對於 cri-o,已經測試了2個後端:runc 和 crun,以測試對 cgroupsv2 的影響。
  • 【轉】在Android Studio中進行單元測試和UI測試
    目錄1.概述2.創建新的Android Studio工程3.配置支持單元測試的工程4.創建第一個單元測試5.運行單元測試6.配置支持Instrumentation測試的工程7.為app添加簡單的交互8.創建並運行Espresso測試
  • 使用 NGINX 和 NGINX Plus 的 Ingress Controller 進行 Kubernetes 的負載均衡
    本文講解了如何使用開源 NGINX 軟體或者 NGINX Plus,以及 Ingress 這個 Kubernetes 自帶的負載均衡框架,對 HTTP 流量進行負載均衡。Ingress 能讓我們配置規則,從而控制外部流向 Kubernetes 集群內的服務的流量。
  • Kubernetes 擴展神器 Argo 實踐
    比如啟動一個測試任務,首先需要從倉庫拉取最新的代碼,然後執行編譯,最後跑批單元測試。這些小的子任務是串行的,必須在前一個任務完成後,才能繼續下一個任務。如果使用Job,不太優雅的做法是每個任務都輪詢上一個任務的狀態直到結束。
  • 在Android Studio中進行單元測試(攻略二)
    【一、Espresso簡介】       Espresso是Google官方的android單元測試框架之一<>(MainActivity.class);這句話就定義了一個測試規則,可以看到構造方法的參數裡指定了一個MainActivity.class,具體的體現就是當你運行這段測試代碼時,app將會直接打開MainActivity界面然後進行你所定義的測試用例。
  • Django項目編寫單元測試用例
    Django 項目中編程單元測試代碼,其實當我們使用 startapp 命令創建 app 應用的時候,你就會發現有一個 tests.py 文件,這個文件就是 Django 提供給開發者做單元測試的,在這個文件中給出了測試類需要繼承的基類 TestCase,其中 django.test.TestCase 是 unittest.TestCase 的一個子類,實現了資料庫訪問以及 HTTP 請求等測試功能
  • 通過 Traefik 使用 Kubernetes Service APIs 進行流量路由
    目前我們可以直接使用 0.10 版本進行安裝:kubectl apply -k "github.com/kubernetes-sigs/service-apis/config/crd?測試下面我們安裝 whoami 服務來進行測試,直接使用下面的資源清單創建對應的服務即可:
  • Android單元測試與模擬測試詳解
    Android領域中這塊還沒有普及,今天主要聊聊Android中的單元測試與模擬測試及其常用的一些庫。    一般單元測試:列出想要測試覆蓋的異常情況,進行驗證。    模擬測試: 根據需求,測試用戶真正在使用過程中,界面的反饋與顯示以及一些依賴系統架構的組件的應用測試。3.
  • Kubernetes 動態創建 Jenkins Agent 壓力測試
    給這些節點打上 Label node-role.kubernetes.io/worker=ci ,用於構建 Pod 選取 Node 使用,避免影響集群上的其他負載。2.5 測試用的 Pipeline DemoDemo 採用的是一個 Java 項目,克隆代碼、執行單元測試、鏡像構建。由於鏡像內容都一樣,這裡就沒有推送鏡像,同時也減少了外部依賴。gitee.com 對拉取頻率也有限制,建議使用自己搭建的代碼倉庫。
  • 【保姆級教程】Spring Boot 單元測試
    單元測試(unit testing),是指對軟體中的最小可測試單元進行檢查和驗證。在Java中單元測試的最小單元是類。\2. 單元測試是開發者編寫的一小段代碼,用於檢驗被測代碼的一個很小的、很明確的功能是否正確。執行單元測試,就是為了證明這 段代碼的行為和我們期望是否一致。