程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> 其他數據庫知識 >> 更多數據庫知識 >> 數據庫單元測試工具-SQLUnit

數據庫單元測試工具-SQLUnit

編輯:更多數據庫知識

   原文信息

  數據庫單元測試工具-SQLUnit

  前言

  正如之前所說,我已經改變了原有寫代碼方式。不是立馬就寫出測試用例的“測試驅動開發”(我知道這種開發理論很難站住腳)。但當我預計到這種編程方式必定存在問題時,這已經是一個好的開始了。在一條帶有自動序列號的主鍵的 INSERT 語句下,我是否應該轉換程序中異常為自己的系統的錯誤代碼?或者僅僅讓 RA-00001 傳播開?我采取的辦法是,僅僅彈出 Oracle 自身提示的錯誤碼,沒有必要自己為出現錯誤再重新創建一套錯誤碼機制。如果你在某種情況下得到一個錯誤碼,已經很嚴肅地告訴了用戶當前有些事情已經出錯了,並且全世界的人都應該知道系統出錯了。

  說說異常吧,使用它們,拋出它們,不要試圖捕捉它們(大部分情況下)並且來做一些其他的事情。將異常記錄下來然後把它們拋向上一層。我想:讓每一個開發者都知道當前狀況已經開始變壞,這是一件很好的事情。我曾花費太多的時間來通過調試代碼來嘗試找出系統的錯誤,但大部分的異常已經被捕捉了而且進程繼續往下跑,導致我浪費了很多時間。至少在某些情況下,我幸運地通過記錄錯誤的日志來解決的問題。

  什麼是 SQLUnit

  SQLUnit 是一個回歸測試數據庫存儲過程的單元測試工具。一個 SQLUnit 測試用例應該用 XML 文件來書寫。SQLUnit工具 是用 Java 實現的,使用 JUnit 單元測試礦建轉換 XML 測試信息到 JDBC 數據庫連接,比較從數據庫中得到的結果和測試用例中的預期結果。不幸的是,它僅僅只持續了三年的開發過程,但我想說的是:這是一個相當好的測試模型。支持存儲過程、函數、游標以及用戶自定義類型(盡管我還沒有嘗試過)。當前最新版本是 5.0.我一直在用的是 1.3 版本。一個大學同學(現在在Oracle 公司工作),在我剛開始使用 SQLUnit 測試工具的時候,他甚至為SQLUnit 中 Oracle 數據庫的測試部分貢獻了代碼。

  我通過它來為 CABEZE 構建數據庫,這是我第一次為自己的事業做的項目,盡管最終沒有成功,但也很好,因為我只是在一些零零碎碎、不太重要的代碼上建立起的項目,所以我可以通過 SQLUnit 來構建整個測試數據(不是測試實際上的產品數據...盡管也沒有實際的設備),建立起數據庫(創建測試數據),運行測試用例並且最後在銷毀階段回滾到原始狀態(空的)。不幸的是,我工作中構建的那個系統不是空的並且是以實際產品進行測試的,或者半生產(清洗) 數據是僅僅是一種可行的替代品.

  回到現在我的狀態。我正嘗試重新認識自己,在這個工具的幫助下為多種多樣的存儲過程書寫測試用例。我跟進一個報出錯誤的測試用例中,因為我們所有的信用卡號都是雜亂的。每一次在不正確的卡號下失敗。攀附之物。

  為什麼不創建一個例程,一個可以生產“實際”信用卡號,更精確的說是:一串已經檢測了數字的合適長度的數列?所以信用卡使用 Luhn 公式用於阻止這些明顯的調換錯誤。

  這 Luhn 算法將檢測任何奇數的錯誤,大部分的調換臨近的數組。它將不是,然而,檢測 調換位置兩數字序列 09-90(或者副動詞)。它將檢測到 在 10 個可能重復數字中檢測出7個(它不能檢測出 22 ? 55, 33 ? 66 or 44 ? 77)。

  在 CABEZE 下,我已經重寫了我自己的 PL/SQL

  卡號生成器(並且通過驗證),但現在我不把它公布出來,而且我好像已經丟失了那部分代碼。所以,我嘗試重寫一遍。

  從我開始使用 SQLUnit 後,我體驗到這個工具演示了一個多麼強大的功能呀!它擁有一些復雜(對於我來說)的公式,所以在寫這些測試用例的時候能夠幫我計算出結果。這是我創建堅持測試基於 Luhn 公式的數字序列。

?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 CREATE OR REPLACE FUNCTION create_check_digit( p_card_number IN NUMBER ) RETURN NUMBER IS   TYPE t_digits IS TABLE OF INTEGER;   l_table T_DIGITS := T_DIGITS();   l_count INTEGER := 0;   l_num INTEGER;   l_digit INTEGER;   l_odd INTEGER := 0;   l_even INTEGER := 0;   l_sum INTEGER := 0;   l_check_digit INTEGER; BEGIN   IF p_card_number IS NULL THEN     raise_application_error( -20001, 'you must provide a card number' );   END IF;     FOR i IN REVERSE 1..LENGTH( p_card_number ) LOOP     l_count := l_count + 1;     l_table.EXTEND(1);     l_table( l_count ) := SUBSTR( p_card_number, i, 1 );   END LOOP;     FOR i IN 1..l_table.COUNT LOOP     l_digit := l_table(i);     IF MOD( i, 2 ) > 0 THEN       l_num := l_digit * 2;       IF l_num > 9 THEN         FOR i IN 1..LENGTH( l_num ) LOOP           l_odd := l_odd + SUBSTR( l_num, i, 1 );         END LOOP;       ELSE         l_odd := l_num;       END IF;       p( 'odd:  ' || l_odd );     ELSE       l_even := l_digit;     END IF;     l_sum := l_sum + l_odd + l_even;     p( 'l_sum:  ' || l_sum );     l_odd := 0;     l_even := 0;   END LOOP;   l_check_digit := ABS( ( CEIL( MOD( l_sum / 10, 10 ) ) * 10 ) - l_sum );   p( 'check digit:  ' || l_check_digit );   p( 'l_sum:  ' || l_sum );   p( p_card_number || l_check_digit );   RETURN l_check_digit; END create_check_digit;

  (譯注:一大堆的 Oracle 存儲過程函數)

  我沒有意識到這可以做到更簡單些,特別是一些常規的表達式。這僅僅是我第一次嘗試...所以不要讓我難堪...如果有更好的解決辦法,請留言。謝謝。 ;)

  這是我最終測試的輸出結果:

?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [sqlunit] *** Running SQLUnit file: p_cc.xml [sqlunit] Getting connection(DEFAULT) [sqlunit] Setting up test... [sqlunit] Running test[1]: PASSING NULL (125ms) [sqlunit] Running test[2]: VALID CARD NUMBER (4992739871) (15ms) [sqlunit] Running test[3]: VALID CARD NUMBER (4012888888881881) (16ms) [sqlunit] Running test[4]: VALID CARD NUMBER (4111111111111111) (0ms) [sqlunit] Running test[5]: VALID CARD NUMBER (4222222222222) (15ms) [sqlunit] Running test[6]: RANDOM (1) NUMBER (5) (0ms) [sqlunit] Running test[7]: RANDOM (2) NUMBER (55) (0ms) [sqlunit] Running test[8]: RANDOM (3) NUMBER (557) (16ms) [sqlunit] Running test[9]: RANDOM (4) NUMBER (5579) (0ms) [sqlunit] Running test[10]: RANDOM (5) NUMBER (65579) (0ms) [sqlunit] Running test[11]: RANDOM (14) NUMBER (12345678965579) (16ms) [sqlunit] Running test[12]: RANDOM NUMBER (5498975) (0ms) [sqlunit] Tearing down test...

  我能夠在很短的時間內運行各種不同的測試用例。之前一個測試運行起來看起來像這樣:

?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 [sqlunit] *** Running SQLUnit file: p_cc.xml [sqlunit] Getting connection(DEFAULT) [sqlunit] Setting up test... [sqlunit] Running test[1]: PASSING NULL (109ms) [sqlunit] Running test[2]: VALID CARD NUMBER (4992739871) (109ms) [sqlunit] Assertion "outparams-equal" failed (6(NUMERIC) != 1(NUMERIC) at outparams[0]) [sqlunit] *** expected: [sqlunit] [sqlunit]   6 [sqlunit] [sqlunit] *** but got: [sqlunit] [sqlunit]   1 [sqlunit] [sqlunit] [sqlunit] Running test[3]: VALID CARD NUMBER (4012888888881881) (0ms) [sqlunit] Running test[4]: VALID CARD NUMBER (4111111111111111) (0ms) [sqlunit] Running test[5]: VALID CARD NUMBER (4222222222222) (0ms) [sqlunit] Assertion "outparams-equal" failed (2(NUMERIC) != 0(NUMERIC) at outparams[0]) [sqlunit] *** expected: [sqlunit] [sqlunit]   2 [sqlunit] [sqlunit] *** but got: [sqlunit] [sqlunit]   0 [sqlunit] [sqlunit] [sqlunit] Running test[6]: RANDOM NUMBER (5498975) (0ms) [sqlunit] Tearing down test... [sqlunit] sqlunit-ant: SQLUnit Tests Failed: In file: p_cc.xml, tests: 6, failures: 2, errors = 0 [sqlunit] SQLUnit Tests Failed: In file: p_cc.xml, tests: 6, failures: 2, errors = 0   我能發現這些問題,並修復它,同時在幾秒內運行這些測試。這看起來是不是非常酷?   這次的測試幫助我意識到如果我傳一串都是奇數的字符串,它將給提示給我錯誤的結果。例如,如果你的 Visa 卡,他是典型的十六位長的數字,並且最後一位數字是對所有數字的驗證。你以除開校驗數以外最右邊的數字開始,並且往回數。這是有將數字放入上面的 PL/SQL 整數表格的趨勢。   我將在以後的測試中指出更多創建的不正確格式的信用卡號,我僅僅想把這個作為 SQLUnit 的一個示例程序。   嘗試。使用。使得我了解它的原理。也許我們能再幸運地遇到一些 Java 程序員將這個項目重新運行起來。

  有用的詞

  anticipat 預支信用證

  certain 必然

  propagated 繁殖 增殖

  regression 衰退 回歸

  harness 工具 馬具

  semi-production 半生產

  cleansed 弄干淨 清洗

  viable alternative 可行的替代品

  reacquaint 重新認識

  scrambled 雜亂無章的

  Barnacles 攀附之物

  transposition 調換 變換

  adjacent 相鄰的 臨近的

  impetus 勢頭 動力

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved