1 00:00:00,057 --> 00:00:01,092 過去幾節課裡 2 00:00:01,092 --> 00:00:03,032 我們花了些時間 3 00:00:03,032 --> 00:00:05,082 談論過不同的測試方法 4 00:00:05,082 --> 00:00:08,021 也談論過單元測試和整合測試的異同 5 00:00:08,021 --> 00:00:10,010 我們也講解過如何使用RSpec 6 00:00:10,010 --> 00:00:12,049 真正將你想測試的程式碼分開 7 00:00:12,049 --> 00:00:14,090 也因為作業三和其他部份的關係 8 00:00:14,090 --> 00:00:18,017 我們也研究過BDD 9 00:00:18,017 --> 00:00:20,062 當中,我們基本上就是使用Cucumber把使用者的流程 10 00:00:20,062 --> 00:00:22,095 轉變成整合測試和合格測試 (acceptance test) 11 00:00:22,095 --> 00:00:25,061 你已經看到不同層次的測試 12 00:00:25,061 --> 00:00:27,063 所以,這節課的目標基本上只是簡單的總結一下而已 13 00:00:27,063 --> 00:00:29,092 就是說,我們站遠點綜觀看看 14 00:00:29,092 --> 00:00:33,001 並將這些事情一起來看 15 00:00:33,001 --> 00:00:34,095 基本上,這節課的內容將會涵蓋 16 00:00:34,095 --> 00:00:37,000 課本上三到四個章節 17 00:00:37,000 --> 00:00:39,061 我在這邊只是稍微提到而已 18 00:00:39,061 --> 00:00:41,046 好了,有一個問題是常常出現的 19 00:00:41,046 --> 00:00:43,025 我想你們也都會有這個問題 20 00:00:43,025 --> 00:00:44,052 因為你們也有做作業 21 00:00:44,052 --> 00:00:45,069 問題就是:「多少測試才夠呢?」 22 00:00:45,069 --> 00:00:48,049 難過的是 23 00:00:48,049 --> 00:00:51,009 如果你們在業界問這個問題 24 00:00:51,009 --> 00:00:52,017 答案是非常簡單的 25 00:00:52,017 --> 00:00:53,017 「關於這個問題,我們有產品的結案日期, 26 00:00:53,017 --> 00:00:54,099 所以在結案日期前能做的測試 27 00:00:54,099 --> 00:00:56,066 即足以。」 28 00:00:56,066 --> 00:00:58,015 也就是有多少時間就做多少 29 00:00:58,015 --> 00:01:00,002 這其實有點顛倒了 30 00:01:00,002 --> 00:01:01,011 顯然不是很好 31 00:01:01,011 --> 00:01:02,054 其實你們可以做的更好,對吧? 32 00:01:02,054 --> 00:01:03,070 這邊有些靜態的測量 33 00:01:03,070 --> 00:01:06,003 像是程式裡有多少程式碼 34 00:01:06,003 --> 00:01:08,021 多少行測試用的程式碼等 35 00:01:08,021 --> 00:01:10,029 另外,在業界並不罕見的是 36 00:01:10,029 --> 00:01:12,068 針對測試完整的程式而言 37 00:01:12,068 --> 00:01:14,057 測試用的程式碼的行數 38 00:01:14,057 --> 00:01:17,073 往往是遠遠超過本來程式碼的行數的 39 00:01:17,073 --> 00:01:19,075 甚至,倍增的量也是常見的 40 00:01:19,075 --> 00:01:21,084 我想,即使甚至是 41 00:01:21,084 --> 00:01:23,022 研究程式碼,甚至是習作等 42 00:01:23,022 --> 00:01:26,085 1.5倍也非不合理 43 00:01:26,085 --> 00:01:30,005 也就是說,測試用的程式碼 44 00:01:30,005 --> 00:01:32,024 有應用程式碼的1.5倍 45 00:01:32,024 --> 00:01:34,022 在很多實作的系統裡 46 00:01:34,022 --> 00:01:35,027 就是說是真正需要測試的 47 00:01:35,027 --> 00:01:36,091 測試程式碼對應用程式碼的比率,甚至比這個更高 48 00:01:36,091 --> 00:01:38,015 所以也許可以用另一個較好的方式來問這個問題 49 00:01:38,015 --> 00:01:39,047 就是,與其問「需要多少測試呢?」 50 00:01:39,047 --> 00:01:42,049 不如問「我現在做的測試有多完整?」 51 00:01:42,049 --> 00:01:44,035 「有多徹底?」 52 00:01:44,035 --> 00:01:45,056 這個學期的後半部 53 00:01:45,056 --> 00:01:46,056 Sen教授將會 54 00:01:46,056 --> 00:01:48,018 對正規方法 (formal methods) 作一個簡略的介紹 55 00:01:48,018 --> 00:01:50,085 並談論一下測試和除錯方法的最新進展 56 00:01:50,085 --> 00:01:52,068 但是,對於這點,現在我們還是可以略提一二的 57 00:01:52,068 --> 00:01:54,007 就是說,基於你們已經知道的,我們還是可以略提 58 00:01:54,007 --> 00:01:57,074 一些有關測試涵蓋率 (test coverage) 的基本概念 59 00:01:57,074 --> 00:01:59,054 我也許會說 60 00:01:59,054 --> 00:02:01,001 事實上我們也一直說 61 00:02:01,001 --> 00:02:03,003 正規方法在大的系統上基本上根本是沒用的 62 00:02:03,003 --> 00:02:05,033 不過,我個人的觀點是 63 00:02:05,033 --> 00:02:07,001 這個說法以前的確很對,但現在已經不太對了 64 00:02:07,001 --> 00:02:09,019 我想,有許多特殊的場合裡 65 00:02:09,019 --> 00:02:10,052 特別在測試和除錯方面 66 00:02:10,052 --> 00:02:12,084 正規測試已經獲得了很大的進展 67 00:02:12,084 --> 00:02:15,075 在這方面 Koushik Sen 是個領導先驅 68 00:02:15,075 --> 00:02:17,094 所以,之後你們都有機會可以了解更多 69 00:02:17,094 --> 00:02:21,043 不過現在我講的,是一些可以說是很實際的東西 70 00:02:21,043 --> 00:02:22,073 就是測試涵蓋率的測量 (coverage measurement) 71 00:02:22,073 --> 00:02:24,047 因為這就是實際情況 72 00:02:24,047 --> 00:02:26,020 換句話說,假如有人要評估你 73 00:02:26,020 --> 00:02:28,063 就是說在真正的工作時有人要評估你,這就是實際情況 74 00:02:28,063 --> 00:02:29,052 那麼,有什麼基礎的東西呢? 75 00:02:29,052 --> 00:02:30,078 讓我給你一個很簡單的類別 76 00:02:30,078 --> 00:02:32,090 來講解有什麼不同的方法來量測 77 00:02:32,090 --> 00:02:34,080 我們的測試可涵蓋多少程式範圍 78 00:02:34,080 --> 00:02:36,063 這邊有些不同的程度差異 79 00:02:36,063 --> 00:02:37,085 以不同的字彙來說的話 80 00:02:37,085 --> 00:02:40,073 這不像是所有的程式部門都通用 81 00:02:40,073 --> 00:02:42,064 但是有一套較通常使用的字彙 82 00:02:42,064 --> 00:02:43,064 是我們的課本裡面用的 83 00:02:43,064 --> 00:02:44,068 就是,我們談到 S0 84 00:02:44,068 --> 00:02:47,045 意思是你呼叫每個方法一次 85 00:02:47,045 --> 00:02:50,045 就是說,你呼叫 foo,然後呼叫 bar,就完成了 86 00:02:50,045 --> 00:02:52,015 這就是 S0 coverage,不是怎麼的全盤 87 00:02:52,015 --> 00:02:54,068 比較嚴謹的 S1 88 00:02:54,068 --> 00:02:56,013 基本上就是,我們呼叫了每一個方法 89 00:02:56,013 --> 00:02:57,028 而且是只要可以呼叫某個方法的地方都去呼叫那個方法 90 00:02:57,028 --> 00:02:58,082 這什麼意思? 91 00:02:58,082 --> 00:03:00,007 舉例來說 92 00:03:00,007 --> 00:03:01,012 只呼叫 bar 不夠 93 00:03:01,012 --> 00:03:02,095 你要先確定你一定會 94 00:03:02,095 --> 00:03:05,057 在這裏呼叫 bar 至少一次 95 00:03:05,057 --> 00:03:07,016 除此以外,還要確定 96 00:03:07,016 --> 00:03:10,037 任何可以呼叫 bar 的外部函數都要呼叫 bar 一次 97 00:03:10,037 --> 00:03:12,081 至於 SimpleCov 所測量的 C0 98 00:03:12,081 --> 00:03:15,099 (你們當中已經設定好 SimpleCov 且實際做過的人啊) 99 00:03:15,099 --> 00:03:18,052 基本上就是表示你執行所有的程式碼 100 00:03:18,052 --> 00:03:20,004 在你的程式碼全部都做過一次 101 00:03:20,004 --> 00:03:22,048 但這邊要小心一下 102 00:03:22,048 --> 00:03:25,058 條件運算只被算一次而已 103 00:03:25,058 --> 00:03:28,091 所以假如發生條件判斷例如執行了 "if" 104 00:03:28,091 --> 00:03:31,074 只要程式碼分支有執行到 105 00:03:31,074 --> 00:03:33,035 你已經執行了 "if" 陳述句 106 00:03:33,035 --> 00:03:35,066 所以 C0 仍然只是涵蓋比較表層的範圍 107 00:03:35,066 --> 00:03:37,026 但是我們將會看到 108 00:03:37,026 --> 00:03:39,023 對 C0 涵蓋率的正確理解,其實是這樣的: 109 00:03:39,023 --> 00:03:41,079 假如 C0 程度的涵蓋率你也測出了不好的涵蓋率 110 00:03:41,079 --> 00:03:44,007 你的測試涵蓋率就真的是非常非常的差了 111 00:03:44,007 --> 00:03:46,008 因為 112 00:03:46,008 --> 00:03:47,037 你如果連這種簡單的表層測試也達不到 113 00:03:47,037 --> 00:03:50,002 你的測試大概很有問題了 114 00:03:50,002 --> 00:03:51,091 C1 則是更進一步 115 00:03:51,091 --> 00:03:53,071 可以這麼說 116 00:03:53,071 --> 00:03:55,019 必須把所有分支雙方向測試 117 00:03:55,019 --> 00:03:56,061 所以當我們在執行 "if" 陳述句 118 00:03:56,061 --> 00:03:58,066 就必須確保 119 00:03:58,066 --> 00:03:59,092 "if x" 這個部分執行到 120 00:03:59,092 --> 00:04:05,013 "if not x"這個部分也至少執行一次,才符合 C1 121 00:04:05,013 --> 00:04:08,036 如果要再進一步,可以再加入 decision coverage 122 00:04:08,036 --> 00:04:09,063 意思是:我們如果想要... 123 00:04:09,063 --> 00:04:12,036 假如我們發現 "if" 陳述句 124 00:04:12,036 --> 00:04:13,088 裡面包含不只一種陳述句 125 00:04:13,088 --> 00:04:15,071 我們必須確保每個陳述句 126 00:04:15,071 --> 00:04:17,097 都可以雙向評估 127 00:04:17,097 --> 00:04:19,067 換句話說 128 00:04:19,067 --> 00:04:22,041 如果 "if" 不執行 129 00:04:22,041 --> 00:04:24,034 就要確保 fail 至少一次 130 00:04:24,034 --> 00:04:26,044 因為 y 至少一次是 false , 又因為 z 是 false 131 00:04:26,044 --> 00:04:28,088 任何陳述句 132 00:04:28,088 --> 00:04:31,021 都是獨立的依條件改變結果 133 00:04:31,021 --> 00:04:34,048 都必須能夠雙向測試 134 00:04:34,048 --> 00:04:36,003 然後 135 00:04:36,003 --> 00:04:38,052 有一件事很多人都希望做到 136 00:04:38,052 --> 00:04:41,026 但沒有共識說這麼做到底有沒有意義 137 00:04:41,026 --> 00:04:42,083 就是每個路徑都走過 138 00:04:42,083 --> 00:04:45,053 顯然,這是有困難度的 139 00:04:45,053 --> 00:04:48,033 因為所有條件都考慮會造成量呈指數倍數的增加 140 00:04:48,033 --> 00:04:53,008 況且,通常都很難去評估 141 00:04:53,008 --> 00:04:55,031 究竟是不是每個路徑都已經測試 142 00:04:55,031 --> 00:04:57,001 針對這些困難的正規方法,是有的 143 00:04:57,001 --> 00:04:58,083 它們可以讓你們知道洞在哪 144 00:04:58,083 --> 00:05:01,031 但是最根本的是 145 00:05:01,031 --> 00:05:03,004 在大部分的商業軟體公司裡 146 00:05:03,004 --> 00:05:04,089 對於 C2 有多少價值的觀念 147 00:05:04,089 --> 00:05:06,070 還不太一致 148 00:05:06,070 --> 00:05:08,068 就是說,C2 比起 C0 或 C1 究竟有多少價值,還是沒有一個共識 149 00:05:08,068 --> 00:05:10,013 所以,我認為,這個課程的用意是 150 00:05:10,013 --> 00:05:11,067 讓你們了解 151 00:05:11,067 --> 00:05:13,020 怎樣使用測試涵蓋率的資訊 152 00:05:13,020 --> 00:05:16,040 SimpleCov 利用 Ruby 中的一些功能 153 00:05:16,040 --> 00:05:18,009 讓你們可以做 C0 測試 154 00:05:18,009 --> 00:05:19,062 也有很好的報表 155 00:05:19,062 --> 00:05:21,025 給我們的資訊 156 00:05:21,025 --> 00:05:22,096 大抵上而言是逐檔案,逐程式行的資訊 157 00:05:22,096 --> 00:05:24,091 你可以看看你的涵蓋範圍 158 00:05:24,091 --> 00:05:27,015 我覺得 159 00:05:27,015 --> 00:05:31,018 這是個很好的開始 160 00:05:31,018 --> 00:05:33,076 我們已經看了不同種類的測試後 161 00:05:33,076 --> 00:05:37,020 往回退一步宏觀的看 162 00:05:37,020 --> 00:05:38,098 我們實際看過的不同的測試 163 00:05:38,098 --> 00:05:40,078 究竟有那幾種? 164 00:05:40,078 --> 00:05:42,032 如果使用不同的測試 165 00:05:42,032 --> 00:05:43,089 各自的缺點又是什麼? 166 00:05:43,089 --> 00:05:47,016 我們已經看過單一類別和方法的程度 167 00:05:47,016 --> 00:05:50,009 我們用 RSpec 大量使用了 mocking 和 stubbing 測試 168 00:05:50,009 --> 00:05:53,004 比如,當我們模型中測試方法 169 00:05:53,004 --> 00:05:55,057 這是單元測試例子 170 00:05:55,057 --> 00:05:59,025 我們也完成其他非常像功能或模組測試 171 00:06:00,097 --> 00:06:02,071 裡面有多個模組 172 00:06:02,071 --> 00:06:04,065 所以如果我們有了 controller 得規格 173 00:06:04,065 --> 00:06:07,085 我們看到就模擬 POST 的行為 174 00:06:07,085 --> 00:06:09,029 但要記住 175 00:06:09,029 --> 00:06:10,086 送出的 POST 要通過 routing subsystem 才到 controller 176 00:06:12,042 --> 00:06:14,048 controller 完成後會產出一個 view 177 00:06:14,048 --> 00:06:16,007 事實上還有其他部分 178 00:06:16,007 --> 00:06:17,067 會和 controller 一起運作 179 00:06:17,067 --> 00:06:19,099 使得 controller 規格能通過 180 00:06:19,099 --> 00:06:21,051 這是裡面的某個部分 181 00:06:21,051 --> 00:06:23,035 我們在這邊有多個方法用到不只一個類別 182 00:06:25,000 --> 00:06:27,000 但我們仍要注意 183 00:06:27,000 --> 00:06:28,088 這只在系統中的一小部分 184 00:06:28,088 --> 00:06:31,044 我們仍廣泛的用 mocking 以及 stubbing 185 00:06:31,044 --> 00:06:35,030 把我們想要測試的行為獨立出來 186 00:06:35,030 --> 00:06:36,091 在 Cucumber 層級的整合或系統測試 187 00:06:38,047 --> 00:06:41,069 他們測試了程式的全部路徑 188 00:06:41,069 --> 00:06:43,044 可能也觸及了相當多不同的模組 189 00:06:43,044 --> 00:06:46,003 最小化使用 mocks 和 stubs 190 00:06:46,003 --> 00:06:48,032 因為整合測試其中一個目標 191 00:06:48,032 --> 00:06:50,099 是能確切的測試個區塊之間的相互影響 192 00:06:50,099 --> 00:06:53,021 所以如果你不想用 stub 或控制這些相互影響 193 00:06:53,021 --> 00:06:54,080 你想要讓系統執行它就會執行 194 00:06:56,030 --> 00:06:58,025 如果這是在開發時 195 00:06:58,025 --> 00:07:00,069 那麼要如何會比較這些不同的測試? 196 00:07:00,069 --> 00:07:02,038 我們看看這邊有幾個不同的軸 197 00:07:02,038 --> 00:07:05,007 其中之一是他們需要多長時間運行 198 00:07:05,007 --> 00:07:06,090 RSpec 和 Cucumber 看似有較高的啟動時間 199 00:07:09,013 --> 00:07:10,008 但如您所見 200 00:07:10,008 --> 00:07:11,090 如果加上更多的 RSpec 測試 201 00:07:11,090 --> 00:07:14,038 並在後臺執行自動測試 202 00:07:14,038 --> 00:07:17,088 一旦 RSpec 開始 203 00:07:17,088 --> 00:07:19,092 會執行 specs 相當快 204 00:07:19,092 --> 00:07:21,095 而 Cucumber 需要很長時間 205 00:07:21,095 --> 00:07:24,059 因為 Cucumber 觸發了整個應用程式 206 00:07:24,059 --> 00:07:26,010 這學期末 207 00:07:26,010 --> 00:07:28,086 我們將會看到讓 Cucumber 更慢 208 00:07:28,086 --> 00:07:30,070 因為整個瀏覽器內部都要觸發 209 00:07:30,070 --> 00:07:33,045 就像是傀儡操控 Firefox 210 00:07:33,045 --> 00:07:35,083 所以可以測試 Javascript 程式 211 00:07:35,083 --> 00:07:37,000 實際上我們做的 212 00:07:37,000 --> 00:07:40,032 我們能和朋友們在 SourceLabs 就在雲端裡操作 213 00:07:40,032 --> 00:07:42,080 真令人興奮 214 00:07:42,080 --> 00:07:45,083 所以執行的快與慢 215 00:07:46,068 --> 00:07:48,025 假如單元測試中發生了錯誤 216 00:07:48,025 --> 00:07:49,075 通常很容易發生 217 00:07:49,075 --> 00:07:52,029 要找出和追蹤該錯誤的來源 218 00:07:52,029 --> 00:07:53,071 正是因為獨立測試 219 00:07:53,071 --> 00:07:56,025 你已經 stub 所以無所謂 220 00:07:56,025 --> 00:07:58,025 你只專注在感興趣的行為 221 00:07:58,025 --> 00:07:59,076 如果已經做得很好但是測試時 有些錯誤的地方又發生錯誤 222 00:08:04,088 --> 00:08:07,041 相反地 如果您用 Cucumber 差不多10個步驟 223 00:08:08,089 --> 00:08:10,031 每一步都會觸擊到應用程式的一部分 224 00:08:11,061 --> 00:08:12,091 這就會花很多時間才能找到那個 bug 225 00:08:14,076 --> 00:08:16,014 所以需要去衡量 能夠涵蓋的錯誤範圍 226 00:08:20,065 --> 00:08:23,002 如果你寫一個好的套件用來作單元測試和功能測試 227 00:08:24,072 --> 00:08:26,020 您可以有很高的覆蓋範圍 228 00:08:26,020 --> 00:08:27,085 您可以產生 SimpleCov 報告 229 00:08:27,085 --> 00:08:30,080 也可以在檔案中的任何一行沒有側試過的程式碼 230 00:08:32,036 --> 00:08:34,016 做會涵蓋到這行的測試 231 00:08:34,016 --> 00:08:36,014 要找出如何改善您的覆蓋範圍 232 00:08:36,014 --> 00:08:37,057 例如在 C0 能更輕鬆地完成與單元測試 233 00:08:40,021 --> 00:08:42,018 而 Cucumber 測試會觸擊大量的程式碼 234 00:08:45,076 --> 00:08:47,080 但你的方法就顯得很少 235 00:08:47,080 --> 00:08:49,038 所以如果目標是提昇涵蓋範圍 236 00:08:49,038 --> 00:08:51,031 就用工具來協助單元的層級 237 00:08:51,031 --> 00:08:53,007 這樣可以更專心去了解程式那邊是不是還沒側過 238 00:08:54,074 --> 00:08:56,055 然後可以寫相當針對性的測試針對這些部分 239 00:08:58,086 --> 00:09:01,043 就像把這些部分放在一起做單元測試 240 00:09:03,039 --> 00:09:05,059 因為這些分離出來測試適合用 mocks 來隔開你不在意的部分 241 00:09:09,012 --> 00:09:11,020 定義上這意味著不是在測試介面 242 00:09:12,070 --> 00:09:14,099 而像是在軟體裡有智慧一樣 243 00:09:14,099 --> 00:09:16,069 很多有趣的錯誤 244 00:09:16,069 --> 00:09:18,076 發生在各部分間的介面 245 00:09:18,076 --> 00:09:20,078 (以下尚未處理) 並在類中或在方法內不進行排序的 246 00:09:20,078 --> 00:09:22,040 那些是有點簡單的 bug,追查 247 00:09:22,040 --> 00:09:24,026 與在另一個極端 248 00:09:24,026 --> 00:09:26,081 你越集成測試走向極端 249 00:09:26,081 --> 00:09:29,072 你應該少依賴類比考試 250 00:09:29,072 --> 00:09:30,090 這一確切原因 251 00:09:30,090 --> 00:09:32,066 現在我們看到的如果你在測試類似 252 00:09:32,066 --> 00:09:34,015 也就是說,在面向服務的體系結構 253 00:09:34,015 --> 00:09:35,089 你要在其上與遠端網站進行交互 254 00:09:35,089 --> 00:09:37,028 你最終仍 255 00:09:37,028 --> 00:09:38,094 不必做了相當大的嘲弄、 鉗 256 00:09:38,094 --> 00:09:40,028 這樣,你不要依賴互聯網 257 00:09:40,028 --> 00:09:41,067 為了使您的測試通過 258 00:09:41,067 --> 00:09:43,006 但是,總體上說 259 00:09:43,006 --> 00:09:47,014 你想盡可能多的類比考試,您可以刪除 260 00:09:47,014 --> 00:09:48,095 而讓系統運行的方式,它將運行在現實生活中 261 00:09:48,095 --> 00:09:52,070 所以,好消息是你 * 是 * 測試介面 262 00:09:52,070 --> 00:09:54,074 * 但 * 當事情出錯在一個介面 263 00:09:54,074 --> 00:09:57,053 因為您的解析度不是那麼好 264 00:09:57,053 --> 00:10:00,031 可能需要很長時間弄清楚它是什麼 265 00:10:00,031 --> 00:10:05,019 那麼,什麼是某種程度的高階位從折 266 00:10:05,019 --> 00:10:07,024 是你真的不想依賴 267 00:10:07,024 --> 00:10:08,076 太重上任何一種測試 268 00:10:08,076 --> 00:10:10,078 他們為不同的目的和具體取決於服務上 269 00:10:10,078 --> 00:10:13,043 你想行使您更多的介面 270 00:10:13,043 --> 00:10:15,089 或你想提高你的細細微性覆蓋率 271 00:10:15,089 --> 00:10:18,003 這會影響你如何發展你的測試套件 272 00:10:18,003 --> 00:10:20,065 和你就會把它演進隨您的軟體 273 00:10:20,065 --> 00:10:24,014 因此,我們使用一組特定的測試中的術語 274 00:10:24,014 --> 00:10:26,028 它是術語到,通過和大 275 00:10:26,028 --> 00:10:29,001 最常用的 Rails 社區 276 00:10:29,001 --> 00:10:30,060 但有一些變化 277 00:10:30,060 --> 00:10:33,069 [和] 你可能會聽到的一些其他術語 278 00:10:33,069 --> 00:10:35,018 如果你去找一份工作的某個地方 279 00:10:35,018 --> 00:10:36,093 你聽到有關變異測試 280 00:10:36,093 --> 00:10:38,072 我們還沒有用過 281 00:10:38,072 --> 00:10:40,024 這是一個有趣的想法,我認為,發明的 282 00:10:40,024 --> 00:10:43,037 維與駕駛艙,有,排序的 283 00:10:43,037 --> 00:10:44,093 軟體測試的通用書 284 00:10:44,093 --> 00:10:46,048 這個想法是: 285 00:10:46,048 --> 00:10:48,000 假設我向我的代碼提交蓄意的 bug 286 00:10:48,000 --> 00:10:49,051 這不會迫使一些測試失敗嗎? 287 00:10:49,051 --> 00:10:53,003 因為,如果我改變,你知道,"如果 x"到"如果不 x" 288 00:10:53,003 --> 00:10:56,010 並沒有測試失敗,然後要麼我的思念一些報導 289 00:10:56,010 --> 00:10:59,019 或我的應用程式是非常奇怪和不知何故不確定性 290 00:10:59,019 --> 00:11:03,099 模糊測試,其中 Koushik 森可能更詳細地談 291 00:11:03,099 --> 00:11:07,085 基本上,這就是"10,000 猴子在打字機 292 00:11:07,085 --> 00:11:09,024 在您的代碼中扔隨機輸入" 293 00:11:09,024 --> 00:11:10,037 有趣的是, 294 00:11:10,037 --> 00:11:11,065 我們一直在做這些測試 295 00:11:11,065 --> 00:11:13,086 基本上是精心編制來測試應用程式 296 00:11:13,086 --> 00:11:15,058 它設計的方法 297 00:11:15,058 --> 00:11:16,088 和這些,你知道,模糊測試 298 00:11:16,088 --> 00:11:19,064 有關測試應用程式的方式是它 * 不是 *,可使用 299 00:11:19,064 --> 00:11:22,098 所以,如果會發生什麼你扔巨大表單提交 300 00:11:22,098 --> 00:11:25,036 如果你把控制字元放在您的表單中,將會發生什麼? 301 00:11:25,036 --> 00:11:27,062 如果您反復提交同樣的事情,會發生什麼? 302 00:11:27,062 --> 00:11:29,093 Koushik 有一個統計資料, 303 00:11:29,093 --> 00:11:32,033 微軟認定他們的 bug 的 20 % 304 00:11:32,033 --> 00:11:34,064 使用一些變異的模糊化測試 305 00:11:34,064 --> 00:11:36,029 和,約 25 % 306 00:11:36,029 --> 00:11:39,021 常見的 Unix 命令列程式的 307 00:11:39,021 --> 00:11:40,092 可以向崩潰 308 00:11:40,092 --> 00:11:44,018 [當] 把侵略性模糊測試通過 309 00:11:44,018 --> 00:11:46,089 定義使用覆蓋範圍是我們還沒有完成的事情 310 00:11:46,089 --> 00:11:48,089 但它是另一個有趣的概念 311 00:11:48,089 --> 00:11:50,089 我的程式在任何一點的設想是, 312 00:11:50,089 --> 00:11:52,062 有一個地方,我的定義 — — 313 00:11:52,062 --> 00:11:54,046 或賦值給一些變數 — — 314 00:11:54,046 --> 00:11:56,000 然後還有下游的地方 315 00:11:56,000 --> 00:11:57,075 大概我的去向消費的價值 — — 316 00:11:57,075 --> 00:11:59,058 有人要使用此值 317 00:11:59,058 --> 00:12:01,013 我已覆蓋每一對嗎? 318 00:12:01,013 --> 00:12:02,059 換句話說,做有測試在每一對 319 00:12:02,059 --> 00:12:04,054 定義一個變數和某個地方使用它 320 00:12:04,054 --> 00:12:07,014 在我的測試套件的某些部分執行 321 00:12:07,014 --> 00:12:10,071 它有時被稱為杜覆蓋範圍 322 00:12:10,071 --> 00:12:14,011 其他條件,我認為不廣泛地不再使用 323 00:12:14,011 --> 00:12:17,071 與白牌或與 glassbox 黑匣子黑匣子 324 00:12:17,071 --> 00:12:20,025 大致上黑匣子測試是一個從寫入 325 00:12:20,025 --> 00:12:22,041 事物的外部規範的角度來看 326 00:12:22,041 --> 00:12:24,022 [例如:]"這是一個雜湊表 327 00:12:24,022 --> 00:12:26,015 當我把放在一個鍵時應回到一個值 328 00:12:26,015 --> 00:12:28,011 如果刪除了關鍵值不存在" 329 00:12:28,011 --> 00:12:29,099 這是一個黑匣子測試,因為它並沒有說 330 00:12:29,099 --> 00:12:32,028 任何有關該雜湊表如何實施的 331 00:12:32,028 --> 00:12:34,072 和它不會嘗試狠抓落實 332 00:12:34,072 --> 00:12:36,056 相應的白牌測試可能是: 333 00:12:36,056 --> 00:12:38,008 "我知道些什麼雜湊函數 334 00:12:38,008 --> 00:12:39,098 和我要去刻意製造 335 00:12:39,098 --> 00:12:41,088 我的測試用例中的雜湊鍵 336 00:12:41,088 --> 00:12:43,078 這造成了大量的散列碰撞 337 00:12:43,078 --> 00:12:45,095 以確保我正在測試的功能,部分" 338 00:12:45,095 --> 00:12:49,007 現在,C0 測試覆蓋工具,像 SimpleCov 339 00:12:49,007 --> 00:12:52,001 將顯示,如果你有的只是黑匣子測試 340 00:12:52,001 --> 00:12:53,028 您可能會發現, 341 00:12:53,028 --> 00:12:55,056 碰撞覆蓋代碼不是很多時候被撞傷 342 00:12:55,056 --> 00:12:56,075 ,可能會提示您,然後說: 343 00:12:56,075 --> 00:12:58,028 "好的如果我真的要加強,— — 344 00:12:58,028 --> 00:13:00,008 第一,如果我想要提高這些測試的覆蓋範圍 345 00:13:00,008 --> 00:13:02,006 現在要寫白牌或 glassbox 測試 346 00:13:02,006 --> 00:13:04,057 我要向內看看,請參閱執行什麼呢 347 00:13:04,057 --> 00:13:05,061 並找到具體的方法 348 00:13:05,061 --> 00:13:10,060 試圖打破邪惡的方式實施" 349 00:13:10,060 --> 00:13:13,075 所以,我認為,測試是一種生活方式,正確嗎? 350 00:13:13,075 --> 00:13:16,069 我們已經遠離的階段 351 00:13:16,069 --> 00:13:18,033 "我們將建立整個事情,然後,我們將考驗" 352 00:13:18,033 --> 00:13:19,092 和我們已經進入的階段 353 00:13:19,092 --> 00:13:20,077 "我們測試我們看一下" 354 00:13:20,077 --> 00:13:22,048 測試是真的更像是一種發展工具 355 00:13:22,048 --> 00:13:24,022 像這麼多的開發工具 356 00:13:24,022 --> 00:13:25,062 它的效力取決於 357 00:13:25,062 --> 00:13:27,013 不管你雅致的方式使用上 358 00:13:27,013 --> 00:13:31,002 所以,你會說:"好吧,讓我們看看 — — 我踢了輪胎 359 00:13:31,002 --> 00:13:33,048 你知道,我解雇了流覽器,我試過幾件事情 360 00:13:33,048 --> 00:13:35,097 (鮮花手)它工作起來 !部署它 !" 361 00:13:35,097 --> 00:13:38,045 這顯然不是你想要的多一點騎士 362 00:13:38,045 --> 00:13:41,024 通過的路上,我們發現的事情之一 363 00:13:41,024 --> 00:13:43,077 與剛剛起步的此線上課程 364 00:13:43,077 --> 00:13:45,090 當 60000 人參加課程 365 00:13:45,090 --> 00:13:48,099 和那些人的 0.1%有問題 366 00:13:48,099 --> 00:13:50,083 你就可以得到 60 電子郵件 367 00:13:50,083 --> 00:13:53,078 必然結果是: 當您的網站使用的很多人 368 00:13:53,078 --> 00:13:55,089 你沒有找到一些愚蠢的 bug 369 00:13:55,089 --> 00:13:57,018 但是,可以通過測試來找 370 00:13:57,018 --> 00:13:59,080 可以非常迅速生成 * 多 * 的痛 371 00:13:59,080 --> 00:14:02,023 另一方面,你不想被教條和說 372 00:14:02,023 --> 00:14:04,056 "呃,直到我們有 100%的覆蓋率和每個測試是綠色 373 00:14:04,056 --> 00:14:06,005 我們絕對會不船舶" 374 00:14:06,005 --> 00:14:07,012 這也是不健康 375 00:14:07,012 --> 00:14:08,048 和測試品質 376 00:14:08,048 --> 00:14:10,057 不一定相符的發言 377 00:14:10,057 --> 00:14:11,064 除非你可以說 378 00:14:11,064 --> 00:14:12,068 關於你的測試品質 379 00:14:12,068 --> 00:14:14,029 只是因為你已經執行的每一條線 380 00:14:14,029 --> 00:14:17,010 並不意味著你測試過的有趣的案件 381 00:14:17,010 --> 00:14:18,068 所以,某處之間,你會說 382 00:14:18,068 --> 00:14:20,014 "嗯,我們可以使用覆蓋工具來標識 383 00:14:20,014 --> 00:14:23,004 undertested 或差測試代碼的部分 384 00:14:23,004 --> 00:14:24,073 我們將使用它們作為指引 385 00:14:24,073 --> 00:14:27,011 要排序的説明改善我們的總體信心水準" 386 00:14:27,011 --> 00:14:29,024 但請記住,敏捷開發是擁抱變化 387 00:14:29,024 --> 00:14:30,032 它的處理 388 00:14:30,032 --> 00:14:32,002 更改的部分是事情會改變,將導致 389 00:14:32,002 --> 00:14:33,038 你沒有預見到的 bug 390 00:14:33,038 --> 00:14:34,031 和正確的反應就是: 391 00:14:34,031 --> 00:14:36,026 能自在的測試工具 392 00:14:36,026 --> 00:14:37,064 [這樣] 您可以快速找到這些 bug 393 00:14:37,064 --> 00:14:39,025 寫一個轉載了這個 bug 的測試 394 00:14:39,025 --> 00:14:40,062 然後進行測試綠色 395 00:14:40,062 --> 00:14:41,061 然後你就會真的改變它 396 00:14:41,061 --> 00:14:43,004 這意味著,您真的修復 bug 的方式是 397 00:14:43,004 --> 00:14:45,049 如果您創建了一個正確的失敗的測試 398 00:14:45,049 --> 00:14:46,088 重現這個 bug 399 00:14:46,088 --> 00:14:48,055 然後回到了並修復該代碼 400 00:14:48,055 --> 00:14:49,057 使這些測試通過 401 00:14:49,057 --> 00:14:51,073 同樣的你不想說 402 00:14:51,073 --> 00:14:53,036 "嗯,單元測試給你更好的覆蓋範圍 403 00:14:53,036 --> 00:14:54,073 他們是更徹底和詳細 404 00:14:54,073 --> 00:14:56,044 所以讓我們專注,我們所有的能量" 405 00:14:56,044 --> 00:14:57,062 而不是 406 00:14:57,062 --> 00:14:58,093 "哦,重點集成測試 407 00:14:58,093 --> 00:15:00,006 因為他們更切合實際,對不對? 408 00:15:00,006 --> 00:15:01,056 它們反映了客戶說他們想要什麼 409 00:15:01,056 --> 00:15:03,034 因此,如果通過集成測試 410 00:15:03,034 --> 00:15:05,067 通過定義我們滿足客戶需求" 411 00:15:05,067 --> 00:15:07,034 同樣,這兩個極端都有點不健康 412 00:15:07,034 --> 00:15:09,079 因為其中的每一個可以找出問題 413 00:15:09,079 --> 00:15:11,031 這將由其他忽略了 414 00:15:11,031 --> 00:15:12,060 所以,有好的結合 415 00:15:12,060 --> 00:15:15,042 就是有點全部是所有關于 416 00:15:15,042 --> 00:15:18,072 我想要留給你們的最後一件事是,我認為 417 00:15:18,072 --> 00:15:20,036 方面的測試,是"與拓展署 418 00:15:20,036 --> 00:15:22,005 所謂傳統的調試 — — 419 00:15:22,005 --> 00:15:24,004 即,我們都有點做的方式 420 00:15:24,004 --> 00:15:25,051 儘管我們說我們不要" 421 00:15:25,051 --> 00:15:26,064 和我們都試圖右好轉嗎? 422 00:15:26,064 --> 00:15:27,085 我們所有的在裝訂線 423 00:15:27,085 --> 00:15:29,036 我們中的一些正仰望星空 424 00:15:29,036 --> 00:15:31,011 努力提高我們的實踐 425 00:15:31,011 --> 00:15:33,099 但現在住這 3 或 4 年我自己 426 00:15:33,099 --> 00:15:35,091 和 — — 要老實 — 3 年前我沒做拓展署 427 00:15:35,091 --> 00:15:37,079 我現在就做,因為我發現它是更好 428 00:15:37,079 --> 00:15:40,081 這裡是我蒸餾的所以,我覺得很管用 429 00:15:40,081 --> 00:15:43,032 很抱歉,顏色是有點怪異 430 00:15:43,032 --> 00:15:45,000 但在左邊的列的表的 431 00:15:45,000 --> 00:15:46,034 [它] 說"常規調試" 432 00:15:46,034 --> 00:15:47,044 右側說"拓展署" 433 00:15:47,044 --> 00:15:49,069 所以我用來編寫代碼的方法是什麼? 434 00:15:49,069 --> 00:15:51,056 也許你們中的一些仍然這樣做 435 00:15:51,056 --> 00:15:53,013 我寫了一大堆的行 436 00:15:53,013 --> 00:15:54,043 也許我們只剩下幾十行代碼 437 00:15:54,043 --> 00:15:55,059 我是 * 確保 * 他們正確 — — 438 00:15:55,059 --> 00:15:56,061 我的意思是,我 * am * 一個好的程式師,正確嗎? 439 00:15:56,061 --> 00:15:57,099 這並不難 440 00:15:57,099 --> 00:15:59,002 我運行它 — — 它不起作用 441 00:15:59,002 --> 00:16:01,098 好的調試器點燃 — — 將 printf 的開始 442 00:16:01,098 --> 00:16:04,088 如果就已經使用 TDD 將我做什麼而是? 443 00:16:04,088 --> 00:16:08,022 嗯,我會寫 * 幾 * 行代碼,第一次寫了一個測試 444 00:16:08,022 --> 00:16:10,071 所以儘快把測試從紅色變為綠色 445 00:16:10,071 --> 00:16:12,064 我知道我寫了代碼的工作 — — 446 00:16:12,064 --> 00:16:15,013 或者至少,我原本想的行為的部件 447 00:16:15,013 --> 00:16:16,096 行為的那些部分工作,因為我有一個測試 448 00:16:16,096 --> 00:16:19,056 好的回傳統的調試: 449 00:16:19,056 --> 00:16:21,073 我正在我的程式試圖找到的 bug 450 00:16:21,073 --> 00:16:23,028 我開始把 printf 的無處不在 451 00:16:23,028 --> 00:16:24,062 可以列印出來的東西值 452 00:16:24,062 --> 00:16:25,064 方式是很有趣 453 00:16:25,064 --> 00:16:26,073 當你想閱讀這些 454 00:16:26,073 --> 00:16:28,014 日誌輸出的 500 線出來的 455 00:16:28,014 --> 00:16:29,035 你會得到一個 Rails 應用程式中 456 00:16:29,035 --> 00:16:30,087 試圖找到 * 你 * printf 的 457 00:16:30,087 --> 00:16:32,035 你知道,"我知道我要做 — — 458 00:16:32,035 --> 00:16:34,008 我要把放在 75 星號之前和之後 459 00:16:34,008 --> 00:16:36,043 這將使可讀"(笑聲) 460 00:16:36,043 --> 00:16:38,071 誰不要 — — 好吧,提高你的手,如果你不這樣做 ! 461 00:16:38,071 --> 00:16:40,090 謝謝你的誠實。(笑聲)還行。 462 00:16:40,090 --> 00:16:43,014 或 — — 或者我可以做其他事情,我可以說: 463 00:16:43,014 --> 00:16:45,030 列印變數的值而不是 464 00:16:45,030 --> 00:16:47,039 為什麼不寫檢查它的測試 465 00:16:47,039 --> 00:16:48,079 在這樣的期望應該 466 00:16:48,079 --> 00:16:50,090 我立即知道在明亮的紅色字母 467 00:16:50,090 --> 00:16:53,033 如果不滿足這一期望 468 00:16:53,033 --> 00:16:56,005 好的我對常規調試側: 469 00:16:56,005 --> 00:16:58,090 我打破出殺手鐧: 我拉出 Ruby 調試器 470 00:16:58,092 --> 00:17:02,044 我設置調試中斷點,和我現在開始 * 調整 * 說 471 00:17:02,044 --> 00:17:04,085 "哦,讓我們看看,我要讓過去的 if 語句 472 00:17:04,085 --> 00:17:06,002 所以要設置的那個東西 473 00:17:06,002 --> 00:17:07,063 哦,我要調用該方法,所以我需要 to…" 474 00:17:07,063 --> 00:17:08,065 不 ! 475 00:17:08,065 --> 00:17:10,087 我 * 能 * 相反 — — 如果我要去做,不管怎麼說 — — 476 00:17:10,087 --> 00:17:13,000 讓我們在檔中設置一些類比考試和存根,只是做 477 00:17:13,000 --> 00:17:16,045 若要控制的代碼路徑,讓它就這樣的方式 478 00:17:16,045 --> 00:17:19,013 現在,"好吧,肯定我已經固定它 ! 479 00:17:19,013 --> 00:17:22,012 我給出的調試器,運行它所有再次 !" 480 00:17:22,012 --> 00:17:24,022 並且,當然,9 次滿分,你並沒有解決它 481 00:17:24,022 --> 00:17:26,072 或你的部分原因是固定的它,但你並沒有完全修復, 482 00:17:26,072 --> 00:17:30,040 現在我再做這些手動都有 483 00:17:30,040 --> 00:17:32,086 * 或 * 我已經有一堆的測試 484 00:17:32,086 --> 00:17:34,031 和我可以自動他們重新 485 00:17:34,031 --> 00:17:35,056 可以,如果有些人不和 486 00:17:35,056 --> 00:17:36,087 "哦,我未修復整件事 487 00:17:36,087 --> 00:17:38,040 沒問題,我只是去回來 !" 488 00:17:38,040 --> 00:17:39,096 所以,底線是, 489 00:17:39,096 --> 00:17:41,095 你知道,你 * 能 * 做它的左側 490 00:17:41,095 --> 00:17:45,004 但在這兩種情況中使用相同的技術 491 00:17:45,004 --> 00:17:48,062 唯一不同的是,在一個案例中你正在手動 492 00:17:48,062 --> 00:17:50,004 這是無聊且容易出錯 493 00:17:50,004 --> 00:17:51,078 在其他情況下你做一些更多的工作 494 00:17:51,078 --> 00:17:53,095 但您可以使它自動和可重複 495 00:17:53,095 --> 00:17:55,071 有,你知道,一些高信心 496 00:17:55,071 --> 00:17:57,003 當您更改您的代碼中的東西 497 00:17:57,003 --> 00:17:58,092 你不打破過去工作的東西 498 00:17:58,092 --> 00:18:00,091 基本上,這是提高工作效率 499 00:18:00,091 --> 00:18:02,047 所以你正在做的事情都一樣 500 00:18:02,047 --> 00:18:04,037 但有一種"三角"額外工作 501 00:18:04,037 --> 00:18:07,086 您正在使用你的努力在多高的杠杆 502 00:18:07,086 --> 00:18:10,036 這樣說是我認為的種 TDD 是一件好事 503 00:18:10,036 --> 00:18:11,088 這是真的,這不需要新的技能 504 00:18:11,088 --> 00:18:15,011 它僅僅需要 [你] 重構您現有的技能 505 00:18:15,011 --> 00:18:18,014 也嘗試過當我 — — 再次,誠實口供,正確嗎? — — 506 00:18:18,014 --> 00:18:19,034 當我開始做這就像 507 00:18:19,034 --> 00:18:21,049 "好吧,我會在滑軌上的課程教學 508 00:18:21,049 --> 00:18:22,065 我真的應該集中測試 509 00:18:22,065 --> 00:18:24,032 所以我回到我寫了一些代碼 510 00:18:24,032 --> 00:18:26,087 那是 * 工作 * — — 你知道,那是體面的代碼 — — 511 00:18:26,087 --> 00:18:29,006 然後我就開始努力為它編寫測試 512 00:18:29,006 --> 00:18:31,019 它是 * 那麼痛苦 * 513 00:18:31,019 --> 00:18:33,033 因為是可測試的方式並不編寫代碼 514 00:18:33,033 --> 00:18:34,097 有各種各樣的交互 515 00:18:34,097 --> 00:18:36,038 比如有嵌套的條件陳述式 516 00:18:36,038 --> 00:18:38,083 如果你想要找出特定語句 517 00:18:38,083 --> 00:18:41,070 並將它測試 — — 到觸發器測試 — — 只是該聲明 518 00:18:41,070 --> 00:18:44,000 你會在您測試設置的東西量 519 00:18:44,000 --> 00:18:45,009 發生 — — 520 00:18:45,009 --> 00:18:46,040 請記住,當談到類比火車殘骸 — — 521 00:18:46,040 --> 00:18:48,014 您必須設置所有此基礎結構 522 00:18:48,014 --> 00:18:49,063 只是為了得到 * 一個 * 代碼行 523 00:18:49,063 --> 00:18:51,015 和你這麼做了,你走 524 00:18:51,015 --> 00:18:52,074 "Gawd,測試是真的不值得 ! 525 00:18:52,074 --> 00:18:54,034 我寫了 20 條線的安裝 526 00:18:54,034 --> 00:18:56,059 這樣我可以測試兩行在函數中我 !" 527 00:18:56,059 --> 00:18:58,085 真正帶告訴你 — — 我現在意識到 — — 528 00:18:58,085 --> 00:19:00,042 是你的函數是 * 壞 * 529 00:19:00,042 --> 00:19:01,049 它是一個嚴重的書面的函數 530 00:19:01,049 --> 00:19:02,052 它不是一個可測試函數 531 00:19:02,052 --> 00:19:03,088 它有太多的移動部件 532 00:19:03,088 --> 00:19:06,026 相關性的 * 可 * 被打破 533 00:19:06,026 --> 00:19:07,070 我的功能中有無接縫 534 00:19:07,070 --> 00:19:11,008 這使我單獨測試不同的行為 535 00:19:11,008 --> 00:19:12,083 一旦你開始做測試第一次開發 536 00:19:12,083 --> 00:19:15,043 因為你要的小塊寫你的測試 537 00:19:15,043 --> 00:19:17,053 它使解決這個問題 538 00:19:17,053 --> 99:59:59,999 所以,這一直是我的頓悟