2013-10-10 47 views
0

我在編寫我正在處理的一段代碼的測試時遇到了麻煩。我有兩個表的,我想創建一個結合表,如下圖所示:爲計算字段創建結點表的記錄並測試進程

CREATE TABLE charges (
    id bigint PRIMARY KEY, 
    amount float, 
    some_data hstore 
) 

CREATE TABLE shipments (
    id bigint PRIMARY KEY, 
    weight float, 
    some_data hstore 
) 

CREATE TABLE distributed_details (
    charges_id bigint references charges (id), 
    shipments_id biging references shipments (id), 
    amount float, 
    another_calculated_field varchar 
) 

根據在some_data領域的一些標準,我也要拉一組的費用和一組出貨量和分發各charges.amount跨越這些貨件shipments.weight。結果將被存儲distributed_details。雖然我正在做這個發佈,但我還需要根據some_data中的剩餘內容執行一些其他計算,這些內容將存儲在distributed_details.another_calculated_field中。

class Distributor 
{ 
    public $detailMapper; 

    public function distribute($charges, $shipments) 
    { 
     foreach ($charges as $charge) { 
      $distributedAmounts = $this->calculateDistributedAmounts($charge->getAmount(), $shipments); 
      foreach ($shipments as $shipment) { 
       $distributed_detail = $this->buildDistributedDetail($charge, $shipment, array_shift($distributedAmounts)); 
       $this->detailMapper->save($distributed_detail); 
      } 
     } 
    } 

    public function calculateDistributedAmounts($shipments) {} 
    public function buildDistributedDetail($charge, $shipment, $distributedAmount) {} 
} 

有沒有一種很好的方法來測試這個函數,並確保這些分佈式數量實際上被拉到並分配給每個記錄?由於內存限制的原因,我已將每個細節的持久性委託給此方法內的detailMapper - 我有時不得不拉動成千上萬的出貨量,並且返回數組中的所有費用將使我內存不足。

回答

0

有點晚了,但我最終開發了一個適當的解決方案來解決這個問題。這裏有兩個大問題:

  1. 表現。將成千上萬的記錄提取到內存中並不是處理這個過程的可行方法。
  2. 可測性。

該解決方案由多個部分組成,以及:

  1. 所有的出貨量不加載到內存中。在我的特殊情況下,我使用了Traversable PDO Statement逐一完成結果。有一點需要注意,它必須第二次重新運行查詢,但可能還有其他方法可以重置指針,而不需要執行此操作。
  2. 將所需的計算從構建每個結點記錄所需的計算分離出來。通過遍歷運輸並分發類似於Martin Fowler's Quantity pattern的實現,我們也可以單獨測試該步驟。
  3. 最後,單獨將記錄保存到您選擇的持久性模式(數據映射器,網關等)。使用這個最後一塊,你可以包裝一切,如果需要的話集成測試。

我沒有一個實際的例子,但這是一般的想法。

1

如果沒有完整的答案是不可能的。我的首選是始終安全地在生產環境中運行測試用例,這意味着他們不會永久向數據庫提交任何內容。儘管我在Perl中做了大部分工作,但相同的測試方法應該能夠爲PHP工作。

  1. 將您的數據庫連接抽象爲處理事務的類。

  2. 不要在自己提交的地方使用自動提交,或者如果確實要確保封裝正確。

  3. 創建一個測試包裝類,您可以替代您的真實連接。這與你的數據庫連接具有完全相同的功能,它避免了自動提交等。區別在於$ database-> commit()是一個noop,所以你的應用程序只認爲它正在提交對數據庫的更改。

這使您可以編寫包括db查詢在內的整個邏輯的測試用例,而不會冒用測試數據污染生產環境的風險。

相關問題