最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

TDD(測試驅(qū)動開發(fā))的意義在哪?

2022-06-08 15:03 作者:西湖大學(xué)空中機(jī)器人  | 我要投稿

在之前的文章中,我們討論了如何使用面向?qū)ο蠛驮O(shè)計模式來設(shè)計算法。然而在實(shí)際的算法開發(fā)中,算法經(jīng)常需要迭代和重構(gòu)。那如何能保證算法的代碼質(zhì)量呢?

為了方便理解,我們以3D投影算法為例。該算法將物體在世界坐標(biāo)系下的坐標(biāo)轉(zhuǎn)換為在相機(jī)圖像中的像素坐標(biāo),涉及三部分:

① 世界坐標(biāo)系轉(zhuǎn)換至相機(jī)坐標(biāo)系

② 相機(jī)坐標(biāo)系轉(zhuǎn)換至圖像坐標(biāo)系

③ 圖像坐標(biāo)系轉(zhuǎn)換到像素坐標(biāo)系

代碼如下(省略了算法細(xì)節(jié)):

void WorldToCamera(const WorldCoordinates& world_coord, ? ? ? ? ? ? ? ? ? CameraCoordinates& camera_coord)

{ ?

// ... ?

// assign value to camera_coord

}

void CameraToImage(const CameraCoordinates& camera_coord,

? ? ? ? ? ? ? ? ImageCoordinates& image_coord)

{

// ... ?

// assign value to image_coord

}

void ImageToPixel(const ImageCoordinates& image_coord,

? ? ? ? ? ? ? ?PixelCoordinates& pixel_coord)

{

// ... ?

// assign value to pixel_coord

}

void WorldToPixel(const WorldCoordinates& world_coord,

? ? ? ? ? ? ? ?PixelCoordinates& pixel_coord)

{

CameraCoordinates camera_coord; ?

ImageCoordinates image_coord; ?

WorldToCamera(world_coord, camera_coord); ?

CameraToImage(camera_coord, image_coord); ?

ImageToPixel(image_coord, pixel_coord);

}

在原有基礎(chǔ)上,我們想優(yōu)化代碼。當(dāng)修改完代碼后發(fā)現(xiàn),最終坐標(biāo)轉(zhuǎn)換結(jié)果錯誤。但是我們無法確定具體是算法中的哪一步驟出了問題。所以我們就開始了漫長的調(diào)試階段。但是,這個過程是很浪費(fèi)時間的。因?yàn)槟悴恢绬栴}出在哪里,所以你就好像是一只“無頭蒼蠅”一樣在代碼中到處調(diào)試,添加斷點(diǎn)、大量的注釋以及打印信息,甚至因著不夠小心,誤刪了或是修改了重要的源代碼而沒有察覺。導(dǎo)致整個調(diào)試過程困難且低效,甚至你的“調(diào)試”會增加更多的bug。那么,如何來解決這個問題呢?

▌ TDD

TDD (Test Driven Development),測試驅(qū)動開發(fā)是一種以測試為優(yōu)先的設(shè)計方法論。通過編寫單元測試用例,保證復(fù)雜系統(tǒng)/算法的開發(fā)和重構(gòu)質(zhì)量。


簡單來說, TDD就是:紅,綠,重構(gòu)。

①首先,非常重要的一點(diǎn)就是“測試先行”。在編寫程序之先,首先寫好測試程序,包括確定測試用例。

②然后才是編寫代碼。當(dāng)代碼初步完成時,運(yùn)行測試程序來驗(yàn)證算法。此時你會發(fā)現(xiàn), 代碼不能通過所有的測試。通過分析這些用例無法通過的原因,修改代碼直至通過全部測試。

③而后便是不斷地重構(gòu)代碼。在此過程中,每次修改代碼都需要通過測試程序的驗(yàn)證。

▌ Gtest

ROS內(nèi)置了gtest模塊,我們可用gtest來實(shí)現(xiàn)TDD。gtest又稱GoogleTest, 是由Google發(fā)布的C++單元測試框架。現(xiàn)在我們?yōu)樯鲜鏊惴ň帉懸粋€測試程序。

// Bring in my package's API, which is what I'm testing

#include <tdd/coordinate.h>

// Bring in gtest

#include <ros/ros.h>

#include <gtest/gtest.h>

TEST(TestSuite, testWorldToCamera)

{ ?

WorldCoordinates world_coord = {200, 300, -20}; ?

CameraCoordinates camera_coord; ?

WorldToCamera(world_coord, camera_coord); ?

EXPECT_EQ(100, camera_coord.x);

EXPECT_EQ(-80, camera_coord.y); ?

EXPECT_EQ(-20, camera_coord.z);

}

TEST(TestSuite, testCameraToImage)

{ ?

CameraCoordinates camera_coord = {100, -80, -20}; ?

ImageCoordinates image_coord; ?

CameraToImage(camera_coord, image_coord); ?

EXPECT_EQ(100, image_coord.x); ?

EXPECT_EQ(-80, image_coord.y);

}

TEST(TestSuite, testImageToPixel)

{ ?

ImageCoordinates image_coord = {100, -80}; ?

PixelCoordinates pixel_coord;

ImageToPixel(image_coord, pixel_coord); ?

EXPECT_EQ(400, pixel_coord.x); ?

EXPECT_EQ(300, pixel_coord.y);

}

TEST(TestSuite, testWorldToPixel)

{ ?

WorldCoordinates world_coord = {200, 300, -20}; ?

PixelCoordinates pixel_coord; ?

WorldToPixel(world_coord, pixel_coord); ?

EXPECT_EQ(400, pixel_coord.x); ?

EXPECT_EQ(300, pixel_coord.y);

}

// Run all the tests that were declared with TEST()

int main(int argc, char **argv){ ?

testing::InitGoogleTest(&argc, argv); ?

ros::init(argc, argv, "tester"); ?

ros::NodeHandle nh; ?return RUN_ALL_TESTS();

}

運(yùn)行測試程序后,若是代碼能通過所有測試用例,將輸出以下結(jié)果:

若是算法中某一部分實(shí)現(xiàn)有錯誤,比如說ImageToPixel坐標(biāo)轉(zhuǎn)換錯誤,將輸出以下結(jié)果:

該輸出結(jié)果告訴我們,WorldToCamera, CameraToImage坐標(biāo)轉(zhuǎn)換正確,而ImageToPixle坐標(biāo)轉(zhuǎn)換錯誤。錯誤值出現(xiàn)在坐標(biāo)的y值上,期望理論值為300,而實(shí)際計算值為200;錯誤的代碼在源文件http://test_coordinate.cc中的41行。

gtest的斷言

斷言在對一個類或函數(shù)進(jìn)行測試時經(jīng)常會使用到。當(dāng)一個斷言,如上述的

失敗時,屏幕上會輸出該代碼所在的源文件及其所在的位置行號,以及錯誤信息。常見的斷言還有,布爾值檢查,數(shù)值型數(shù)據(jù)檢查,字符串比較,異常檢查,浮點(diǎn)型檢查,類型檢查等。

快速反饋

通過運(yùn)行測試程序輸出的信息,我們能快速得到反饋,從而得知算法中的哪一步驟出現(xiàn)問題。表面上看,編寫測試程序增加了代碼量;實(shí)際上在后續(xù)的算法開發(fā)和重構(gòu)階段會為我們節(jié)省大量的時間。如上述所示,我們快速定位到ImageToPixle出現(xiàn)問題,只需要關(guān)注該部分代碼而無需再去檢查其他部分的代碼。并且,每一次測試我們都不需要去做額外的工作,如準(zhǔn)備測試數(shù)據(jù),啟動節(jié)點(diǎn)等,這些都包含在測試程序里。

確保代碼質(zhì)量

通過合適且足夠的測試用例來覆蓋算法的各步驟所涉及的各種情況,為算法提供全方位的質(zhì)量保證。

▌ 總結(jié)

在這篇文章中,我們介紹如何使用gtest在ROS中實(shí)現(xiàn)了TDD,并將其運(yùn)用在算法開發(fā)和重構(gòu)中,提高了開發(fā)效率并保證了代碼質(zhì)量。關(guān)于更多gtest的使用,可查閱參考資料。


參考資料

1.?https://google.github.io/googletest/

2.?http://wiki.ros.org/gtest


本文共1455字

由西湖大學(xué)智能無人系統(tǒng)實(shí)驗(yàn)室工程師陳華奔原創(chuàng)

申請文章授權(quán)請聯(lián)系后臺相關(guān)運(yùn)營人員

▌微信公眾號:空中機(jī)器人前沿

▌知乎:空中機(jī)器人前沿(本文鏈接:https://www.zhihu.com/question/329784671/answer/2483642856)

▌Youtube:Aerial robotics @ Westlake University

▌實(shí)驗(yàn)室網(wǎng)站:https://shiyuzhao.westlake.edu.cn/


TDD(測試驅(qū)動開發(fā))的意義在哪?的評論 (共 條)

分享到微博請遵守國家法律
阳东县| 连山| 调兵山市| 古蔺县| 龙陵县| 胶南市| 昌吉市| 壶关县| 新野县| 茂名市| 漾濞| 阿巴嘎旗| 秀山| 东安县| 洞头县| 察哈| 淅川县| 故城县| 赤峰市| 云南省| 徐州市| 林芝县| 农安县| 和平县| 灌阳县| 息烽县| 宁安市| 梁河县| 吴江市| 新津县| 台南县| 三明市| 五原县| 闽侯县| 岑溪市| 建宁县| 永州市| 贞丰县| 聂拉木县| 新竹县| 高碑店市|