2010-07-14 26 views
6

我典型場景:如何生成源代碼來創建我正在調試的對象?

  1. 遺留代碼,我的工作了,只有在生產客戶是有
  2. 我附上一個調試器,並找出如何重現上他們系統問題的錯誤給出輸入。但是,我不知道爲什麼錯誤還在發生。
  3. 現在我想寫我的本地系統上的自動化測試,試圖重現然後修正錯誤

這最後一步是真的很難。輸入可能非常複雜,並且有很多數據。手工創建輸入(例如:想象做1000次來創建對象)是非常乏味和容易出錯的。事實上,您可能會注意到我剛剛給出的示例中存在拼寫錯誤。

是否有一種自動方式從我的調試器的中斷點取得一個字段,並生成將創建該對象的源代碼,填充方式相同?

我唯一想出的就是序列化這個輸入(例如使用Xstream)。我可以將它保存到一個文件中,並在自動化測試中讀回。這有一個主要問題:如果類以某種方式改變(例如:字段/ getter/setter名稱被重命名),我將無法反序列化對象。換句話說,測試非常脆弱。

+1

你能否澄清爲什麼像XStream這樣的東西不適合,爲什麼你絕對需要生成源代碼?這肯定會有助於獲得更好的答案。 – 2010-07-14 23:53:11

+1

您想要現在解決的現場測試事件的測試用例的長期脆弱性有什麼問題? – 2013-01-12 23:51:02

+0

@IraBaxter短期內沒有任何問題。但是如果有一些很酷的圖書館/技術/策略可以比我現在更好地處理這個問題,我想聽聽它。 – 2013-01-13 00:13:23

回答

2

當標準對象更改其版本(內容,字段命名)時,Java標準序列化並不是非常有用。它適用於快速演示項目。

更適合您的需求,是objetcs支持你自己的(二進制)自定義序列的方法:
這並不困難,使用DataOutputStream寫出對象的所有領域。但現在通過首先寫出一個versionId來引入versiong。只有一個版本的對象寫出versionId 1.這樣,稍後,當您必須在objetcs中引入更改時,可以刪除字段,添加字段,提高版本號。

這種ICustomSerializable然後將第一讀出從輸入流中的版本號,在readObject()方法,並且取決於版本ID調用readVersionV1()或例如readVersionV2().

public Interface ICustomSerializable { 
    void writeObject(DataOutputStream dos); 
    Object readObject(DataInputStream dis); 
} 

public Class Foo { 
    public static final VERSION_V1 = 1; 
    public static final VERSION_V2 = 2; 

    public static final CURRENT_VERSION = VERSION_V2; 
    private int version; 

    private int fooNumber; 
    private double fooDouble; 

    public void writeObject(DataOutputStream dos) { 
    dos.writeInt(this.version); 
     if (version == VERSION_V1) { 
      writeVersionV1(dos); 
     } else (version == VERSION_V2) { 
      writeVersionV2(dos); 
     } else { 
     throw new IllegalFormatException("unkown version: " + this.version); 
     } 
    } 
    public void writeVersionV1(DataOutputStream dos) { 
     writeInt(this.fooNumber); 
     writeDouble(this.fooValue); 
    } 
} 

此外吸氣劑和setter,並且需要一個將版本初始化爲CURRENT_VERSION的構造函數。

如果您更改或添加適當的讀寫版本,這種serialisazion可以安全地重構。對於使用來自外部庫的類而不是您的控件的複雜對象,可以做更多的工作,但是字符串和列表很容易被序列化。

+0

這是一個有趣的方法。實際上,我正在考慮編寫我自己的xstream串行器來編寫源代碼(如果這甚至是一個選項)。我不喜歡這個建議的事情是構建中斷可能是通知我我必須實現'writeVersionV2'的東西。我不想在這種情況下寫下它。 – 2013-01-18 18:01:30

1

我認爲你想要做的就是存儲「狀態」,然後在你的測試中恢復,以確保bug保持固定。

簡短的回答:有一個afaik沒有這樣的通用代碼生成工具,但只要保留幾個約束,編寫這樣的工具是一件小事。

長評論: 有限制下,可以工作。如果所有東西都只是帶有getter和setter的beans,那麼爲其生成代碼並不困難。如果重構生成的代碼和普通代碼一樣,那麼重命名是安全的。如果setter缺失,那麼這種方法將不起作用。這僅僅是爲什麼這不是一般解決方案的一個例子。

重構還可以例如將字段移動到其他類。你想如何介紹該類別其他領域的價值觀?你怎麼能後來知道他們是否改變了你保存的狀態仍然反映了關鍵數據?或者更糟糕的是,想象重構給了同一個領域與以前不同的意義。

錯誤本身的性質也是一個約束。想象一下,例如發生了這個錯誤,因爲一個字段/方法有這個名字和這個名字。如果重構現在改變了名稱,那麼無論您的狀態如何,該錯誤都不會再出現。

這些只是任意的例子,可能與您的真實生活案例完全無關。但是,這是案件判決的案件,而不是一般戰略。無論如何,如果你知道你的代碼,錯誤和你的重構對此都足夠好,那麼使這樣一個工具在不到一天的時間內完成,可能要少得多。

在xstream中,你也可以部分得到它,但是你必須自己改變xml。如果你使用db4o,你必須告訴它,這個和那個字段現在有這個和那個名字。

相關問題