<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                #### [DbC + 單元測試](https://lingcoder.gitee.io/onjava8/#/book/16-Validating-Your-Code?id=dbc-%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95) 下面的例子演示了將契約式設計中的概念與單元測試相結合的有效性。它顯示了一個簡單的先進先出(FIFO)隊列,該隊列實現為一個“循環”數組,即以循環方式使用的數組。當到達數組的末尾時,將繞回到開頭。 我們可以對這個隊列做一些契約定義: **1**. 前置條件(用于put()):不允許將空元素添加到隊列中。 **2**. 前置條件(用于put()):將元素放入完整隊列是非法的。 **3**. 前置條件(用于get()):試圖從空隊列中獲取元素是非法的。 **4**. 后置條件用于get()):不能從數組中生成空元素。 **5**. 不變性:包含對象的區域不能包含任何空元素。 **6**. 不變性:不包含對象的區域必須只有空值。 下面是實現這些規則的一種方式,為每個 DbC 元素類型使用顯式的方法調用。 首先,我們創建一個專用的**Exception**: ~~~ // validating/CircularQueueException.java package validating; public class CircularQueueException extends RuntimeException { public CircularQueueException(String why) { super(why); } } ~~~ 它用來報告**CircularQueue**中出現的錯誤: ~~~ // validating/CircularQueue.java // Demonstration of Design by Contract (DbC) package validating; import java.util.*; public class CircularQueue { private Object[] data; private int in = 0, // Next available storage space out = 0; // Next gettable object // Has it wrapped around the circular queue? private boolean wrapped = false; public CircularQueue(int size) { data = new Object[size]; // Must be true after construction: assert invariant(); } public boolean empty() { return !wrapped && in == out; } public boolean full() { return wrapped && in == out; } public boolean isWrapped() { return wrapped; } public void put(Object item) { precondition(item != null, "put() null item"); precondition(!full(), "put() into full CircularQueue"); assert invariant(); data[in++] = item; if(in >= data.length) { in = 0; wrapped = true; } assert invariant(); } public Object get() { precondition(!empty(), "get() from empty CircularQueue"); assert invariant(); Object returnVal = data[out]; data[out] = null; out++; if(out >= data.length) { out = 0; wrapped = false; } assert postcondition( returnVal != null, "Null item in CircularQueue"); assert invariant(); return returnVal; } // Design-by-contract support methods: private static void precondition(boolean cond, String msg) { if(!cond) throw new CircularQueueException(msg); } private static boolean postcondition(boolean cond, String msg) { if(!cond) throw new CircularQueueException(msg); return true; } private boolean invariant() { // Guarantee that no null values are in the // region of 'data' that holds objects: for(int i = out; i != in; i = (i + 1) % data.length) if(data[i] == null) throw new CircularQueueException("null in CircularQueue"); // Guarantee that only null values are outside the // region of 'data' that holds objects: if(full()) return true; for(int i = in; i != out; i = (i + 1) % data.length) if(data[i] != null) throw new CircularQueueException( "non-null outside of CircularQueue range: " + dump()); return true; } public String dump() { return "in = " + in + ", out = " + out + ", full() = " + full() + ", empty() = " + empty() + ", CircularQueue = " + Arrays.asList(data); } } ~~~ **in**計數器指示數組中下一個對象所在的位置。**out**計數器指示下一個對象來自何處。**wrapped**的flag表示**in**已經“繞著圓圈”走了,現在從后面出來了。當**in**和**out**重合時,隊列為空(如果包裝為**false**)或滿(如果**wrapped**為**true**)。 **put()**和**get()**方法調用**precondition()**,**postcondition()**, 和**invariant**(),這些都是在類中定義的私有方法。前置**precondition()**和**postcondition()**是用來闡明代碼的輔助方法。 注意,**precondition()**返回**void**, 因為它不與斷言一起使用。按照之前所說的,通常你會在代碼中保留前置條件。通過將它們封裝在**precondition()**方法調用中,如果你不得不做出關掉它們的可怕舉動,你會有更好的選擇。 **postcondition()**和**invariant()**都返回一個布爾值,因此可以在**assert**語句中使用它們。此外,如果出于性能考慮禁用斷言,則根本不存在方法調用。**invariant()**對對象執行內部有效性檢查,如果你在每個方法調用的開始和結束都這樣做,這是一個花銷巨大的操作,就像**Meyer**建議的那樣。所以, 用代碼清晰地表明是有幫助的,它幫助我調試了實現。此外,如果你對代碼實現做任何更改,那么**invariant()**將確保你沒有破壞代碼,將不變性測試從方法調用移到單元測試代碼中是相當簡單的。如果你的單元測試是足夠的,那么你應當對不變性保持一定的信心。 **dump()**幫助方法返回一個包含所有數據的字符串,而不是直接打印數據。這允許我們用這部分信息做更多事。 現在我們可以為類創建 JUnit 測試: ~~~ // validating/tests/CircularQueueTest.java package validating; import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assertions.*; public class CircularQueueTest { private CircularQueue queue = new CircularQueue(10); private int i = 0; @BeforeEach public void initialize() { while(i < 5) // Pre-load with some data queue.put(Integer.toString(i++)); } // Support methods: private void showFullness() { assertTrue(queue.full()); assertFalse(queue.empty()); System.out.println(queue.dump()); } private void showEmptiness() { assertFalse(queue.full()); assertTrue(queue.empty()); System.out.println(queue.dump()); } @Test public void full() { System.out.println("testFull"); System.out.println(queue.dump()); System.out.println(queue.get()); System.out.println(queue.get()); while(!queue.full()) queue.put(Integer.toString(i++)); String msg = ""; try { queue.put(""); } catch(CircularQueueException e) { msg = e.getMessage(); ?System.out.println(msg); } assertEquals(msg, "put() into full CircularQueue"); showFullness(); } @Test public void empty() { System.out.println("testEmpty"); while(!queue.empty()) System.out.println(queue.get()); String msg = ""; try { queue.get(); } catch(CircularQueueException e) { msg = e.getMessage(); System.out.println(msg); } assertEquals(msg, "get() from empty CircularQueue"); showEmptiness(); } @Test public void nullPut() { System.out.println("testNullPut"); String msg = ""; try { queue.put(null); } catch(CircularQueueException e) { msg = e.getMessage(); System.out.println(msg); } assertEquals(msg, "put() null item"); } @Test public void circularity() { System.out.println("testCircularity"); while(!queue.full()) queue.put(Integer.toString(i++)); showFullness(); assertTrue(queue.isWrapped()); while(!queue.empty()) System.out.println(queue.get()); showEmptiness(); while(!queue.full()) queue.put(Integer.toString(i++)); showFullness(); while(!queue.empty()) System.out.println(queue.get()); showEmptiness(); } } /* Output: testNullPut put() null item testCircularity in = 0, out = 0, full() = true, empty() = false, CircularQueue = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 0 1 2 3 4 5 6 7 8 9 in = 0, out = 0, full() = false, empty() = true, CircularQueue = [null, null, null, null, null, null, null, null, null, null] in = 0, out = 0, full() = true, empty() = false, CircularQueue = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 10 11 12 13 14 15 16 17 18 19 in = 0, out = 0, full() = false, empty() = true, CircularQueue = [null, null, null, null, null, null, null, null, null, null] testFull in = 5, out = 0, full() = false, empty() = false, CircularQueue = [0, 1, 2, 3, 4, null, null, null, null, null] 0 1 put() into full CircularQueue in = 2, out = 2, full() = true, empty() = false, CircularQueue = [10, 11, 2, 3, 4, 5, 6, 7, 8, 9] testEmpty 0 1 2 3 4 get() from empty CircularQueue in = 5, out = 5, full() = false, empty() = true, CircularQueue = [null, null, null, null, null, null, null, null, null, null] */ ~~~ **initialize()**添加了一些數據,因此每個測試的**CircularQueue**都是部分滿的。**showFullness()**和**showempty()**表明**CircularQueue**是滿的還是空的,這四種測試方法中的每一種都確保了**CircularQueue**功能在不同的地方正確運行。 通過將 Dbc 和單元測試結合起來,你不僅可以同時使用這兩種方法,還可以有一個遷移路徑—你可以將一些 Dbc 測試遷移到單元測試中,而不是簡單地禁用它們,這樣你仍然有一定程度的測試。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看