日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

junit测试找不到数据库_将数据库日志添加到JUnit3

發(fā)布時間:2023/12/3 数据库 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 junit测试找不到数据库_将数据库日志添加到JUnit3 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

junit測試找不到數(shù)據(jù)庫

在過去的十年中,我們已經(jīng)編寫了成千上萬的JUnit3測試,現(xiàn)在正嘗試將結(jié)果合并到數(shù)據(jù)庫中,而不是分散的日志文件中。 事實(shí)證明,擴(kuò)展TestCase類非常容易做到這一點(diǎn)。 注意:這種方法并不直接適用于JUnit4或其他測試框架,但是通常可以做類似的事情。

被測類及其測驗(yàn)

出于演示目的,我們可以使用單個方法來定義一個類進(jìn)行測試。

public class MyTestedClass {public String op(String a, String b) {return ((a == null) ? "" : a) + ":" + ((b == null) ? "" : b);} }

具有單個要測試方法的類比您想象的要少的限制。 在前面提到的數(shù)千個測試中,我們僅測試了四種方法。

這是上述類的一些測試。

public class MySimpleTest extends SimpleTestCase {private MyTestedClass obj = new MyTestedClass();public void test1() {assertEquals("a:b", obj.op("a", "b"));}public void test2() {assertEquals(":b", obj.op(null, "b"));}public void test3() {assertEquals("a:", obj.op("a", null));}public void test4() {assertEquals(":", obj.op(null, null));}public void test5() {// this will failassertEquals(" : ", obj.op(null, null));} }

使用TestListener捕獲基本信息

JUnit3允許向偵聽器添加其測試過程。 在測試運(yùn)行之前和之后以及測試失敗或有錯誤(引發(fā)異常)的任何時間調(diào)用此偵聽器。 該TestListener將基本測試信息寫入System.out,以作為概念證明。 修改它以將信息寫入數(shù)據(jù)庫,JMS主題等很容易。

public class SimpleTestListener implements TestListener {private static final TimeZone UTC = TimeZone.getTimeZone("UTC");private long start;private boolean successful = true;private String name;private String failure = null;SimpleTestListener() {}public void setName(String name) {this.name = name;}public void startTest(Test test) {start = System.currentTimeMillis();}public void addError(Test test, Throwable t) {// cache information about error.successful = false;}public void addFailure(Test test, AssertionFailedError e) {// cache information about failure.failure = e.getMessage();successful = false;}/*** After the test finishes we can update the database with statistics about* the test - name, elapsed time, whether it was successful, etc.*/public void endTest(Test test) {long elapsed = System.currentTimeMillis() - start;SimpleDateFormat fmt = new SimpleDateFormat();fmt.setTimeZone(UTC);System.out.printf("[%s, %s, %s, %d, %s, %s]\n", test.getClass().getName(), name, fmt.format(new Date(start)),elapsed, failure, Boolean.toString(successful));// write any information about errors or failures to database.} }

生產(chǎn)TestListener應(yīng)該在錯誤和失敗方面做更多的事情。 我將其忽略,以便專注于更廣泛的問題。

該偵聽器不是線程安全的,因此我們將要使用Factory模式為每個測試創(chuàng)建一個新實(shí)例。 我們可以在工廠中創(chuàng)建重量級對象,例如,在工廠中打開SQL DataSource并將新的Connection傳遞給每個實(shí)例。

public class SimpleTestListenerFactory {public static final SimpleTestListenerFactory INSTANCE = new SimpleTestListenerFactory();public SimpleTestListenerFactory() {// establish connection data source here?}public SimpleTestListener newInstance() {// initialize listener.SimpleTestListener listener = new SimpleTestListener();return listener;} }

如果我們知道測試框架是純串行的,則可以通過創(chuàng)建緩沖區(qū)并在startTest()中調(diào)用System.setOut(),然后在endTest()中還原原始System.out來捕獲所有控制臺輸出。 只要測試永不重疊,此方法就行得通,否則會引起問題。 但是,這可能會出現(xiàn)問題– IDE可能具有自己的允許并行執(zhí)行的測試運(yùn)行程序。

我們用自己的方法覆蓋標(biāo)準(zhǔn)的run()方法,該方法在調(diào)用現(xiàn)有的run()方法之前創(chuàng)建并注冊一個偵聽器。

public class SimpleTestCase extends TestCase {public void run(TestResult result) {SimpleTestListener l = SimpleTestListenerFactory.INSTANCE.newInstance();result.addListener(l);l.setName(getName());super.run(result);result.removeListener(l);}}

現(xiàn)在,我們將預(yù)期的結(jié)果發(fā)送到System.out。

[MySimpleTest, test1, 8/2/15 11:58 PM, 0, null, true] [MySimpleTest, test2, 8/2/15 11:58 PM, 10, null, true] [MySimpleTest, test3, 8/2/15 11:58 PM, 0, null, true] [MySimpleTest, test4, 8/2/15 11:58 PM, 0, null, true] [MySimpleTest, test5, 8/2/15 11:58 PM, 4, expected same:<:> was not:< : >, false]

使用外觀和TestListener捕獲呼叫信息

這是一個好的開始,但我們可能會做得更好。 在上面提到的數(shù)千個測試中,僅調(diào)用了4種方法-如果我們可以捕獲這些調(diào)用的輸入和輸出值,則將非常強(qiáng)大。

如果由于某些原因不接受AOP,則可以使用AOP或日志記錄外觀包裝這些功能。 在簡單的情況下,我們可以簡單地捕獲輸入和輸出值。

public class MyFacadeClass extends MyTestedClass {private MyTestedClass parent;private String a;private String b;private String result;public MyFacadeClass(MyTestedClass parent) {this.parent = parent;}public String getA() {return a;}public String getB() {return b;}public String getResult() {return result;}/*** Wrap tested method so we can capture input and output.*/public String op(String a, String b) {this.a = a;this.b = b;String result = parent.op(a, b);this.result = result;return result;}}

我們像以前一樣記錄基本信息,并添加一些新代碼來記錄輸入和輸出。

public class AdvancedTestListener extends SimpleTestListener {AdvancedTestListener() {}/*** Log information as before but also log call details.*/public void endTest(Test test) {super.endTest(test);// add captured inputs and outputsif (test instanceof MyAdvancedTest) {MyTestedClass obj = ((MyAdvancedTest) test).obj;if (obj instanceof MyFacadeClass) {MyFacadeClass facade = (MyFacadeClass) obj;System.out.printf("[, , %s, %s, %s]\n", facade.getA(), facade.getB(), facade.getResult());}}} }

日志現(xiàn)在顯示基本信息和呼叫詳細(xì)信息。

[MyAdvancedTest, test2, 8/3/15 12:13 AM, 33, null, true] [, , null, b, :b] [MyAdvancedTest, test3, 8/3/15 12:13 AM, 0, null, true] [, , a, null, a:] [MyAdvancedTest, test4, 8/3/15 12:13 AM, 0, null, true] [, , null, null, :] [MyAdvancedTest, test1, 8/3/15 12:13 AM, 0, null, true] [, , a, b, a:b]

我們希望將基本詳細(xì)信息和呼叫詳細(xì)信息相關(guān)聯(lián),但是通過添加唯一的測試ID可以輕松實(shí)現(xiàn)。

在現(xiàn)實(shí)世界中,這種方法還不夠,在單個測試中,被測方法可能被多次調(diào)用。 在這種情況下,我們需要一種緩存多組輸入和輸出值的方法,或者擴(kuò)展偵聽器,以便我們可以在每個涵蓋方法的末尾調(diào)用它。

通過將結(jié)果編碼為XML或JSON而不是簡單的列表,可以使結(jié)果更具擴(kuò)展性。 這將使我們僅捕獲感興趣的值或輕松處理將來添加的字段。

[MyAdvancedTest, test2, 8/3/15 12:13 AM, 33, null, true] {"a":null, "b":"b", "results":":b" } [MyAdvancedTest, test3, 8/3/15 12:13 AM, 0, null, true] {"a":"a", "b":null, "results":"a:" } [MyAdvancedTest, test4, 8/3/15 12:13 AM, 0, null, true] {"a":null, "b":null, "results":":" } [MyAdvancedTest, test1, 8/3/15 12:13 AM, 0, null, true] {"a":" a", "b":"b", "results":" a:b" }

捕獲

現(xiàn)在,我們可以通過重放捕獲的輸入來重新運(yùn)行測試,但是盲目比較結(jié)果存在兩個問題。 首先,如果我們只關(guān)心單個值,這將是很多不必要的工作。 其次,許多測試是不確定的(例如,它們使用隨時間變化的固定數(shù)據(jù)甚至實(shí)時數(shù)據(jù)),而我們不關(guān)心的事情可能會改變。

這不是一個容易的問題。 如果幸運(yùn)的話,測試將遵循標(biāo)準(zhǔn)模式,我們可以對正在執(zhí)行的測試做出很好的猜測,但需要手動進(jìn)行驗(yàn)證。

首先,我們需要使用捕獲某些或所有方法調(diào)用的外觀包裝測試方法的結(jié)果。 調(diào)用歷史記錄應(yīng)該以一種我們以后可以重播的形式提供,例如一系列方法名稱和序列化參數(shù)。

其次,我們需要包裝TestCase assertX方法,以便捕獲最近的方法調(diào)用以及傳遞給assert調(diào)用的值(當(dāng)然還有結(jié)果)。

通過示例最容易展示和刪除該過程。 讓我們從一個簡單的POJO開始。

public class Person {private String firstName;private String lastName;public String getFirstName() { return firstName; }public String getLastName() { return lastName; } }

在這種情況下,我們的外觀僅需要記錄方法名稱。

典型的測試方法是

public void test1() {Person p = getTestPerson();assertEquals("John", p.getFirstName());assertEquals("Smith", p.getLastName()); }

使用包裝的assertX方法

static PersonFacade person;public static void assertEquals(String expected, String actual) {// ignoring null handling...boolean results = expected.equals(actual);LOG.log("assertEquals('" + expected + "',"+person.getMethodsCalled()+ ") = " + results);person.clearMethodsCalled();if (!results) {throw new AssertionFailedError("Expected same:<" + expected + " > was not:<" + actual + ">");} }

所以我們會得到像

assertEquals('John', getFirstName()) = true; assertEquals('Smith', getLastName()) = false;

不難看出如何通過測試框架來解析它,但是現(xiàn)在還為時過早。 第二種測試方法是

public void test1() {Person p = getTestPerson();assertEquals("john", p.getFirstName().toLowerCase()); }

并且我們的簡單代碼不會捕獲toLowerCase() 。 我們的日志將錯誤記錄:

assertEquals('John', getFirstName()) = false;

更為病理的情況是:

public void test1() {Person p = getTestPerson();LOG.log("testing " + p.getFirstName());assertEquals("john", "joe"); }

斷言與包裝的類無關(guān)。

有明顯的創(chuàng)可貼,例如,我們可以捕獲外觀中的返回值,但這是一個非常深的兔子洞,我們希望遠(yuǎn)離它。 我認(rèn)為答案是做出合理的第一次嘗試,手動驗(yàn)證結(jié)果,然后再做。 (替代:將測試重寫為可以捕獲的形式。)

翻譯自: https://www.javacodegeeks.com/2015/08/adding-database-logging-to-junit3.html

junit測試找不到數(shù)據(jù)庫

總結(jié)

以上是生活随笔為你收集整理的junit测试找不到数据库_将数据库日志添加到JUnit3的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。