validating - DBC + Unit Testing

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangbingfengf98/article/details/88917610

DBC: Design by Contract.

For example

We make 6 contractual definitons for the queue:

  1. Precondition (for a put()): Null elements are not allowed to be added to the queue.
  2. Precondition (for a put()): It is illegal to put elements into a full queue.
  3. Precondition (for a get()): It is illegal to try to get elements from an empty queue.
  4. Precondition (for a get()): Null elements cannot be produced from the array.
  5. Invariant: The region that contains objects cannot contain any null elements.
  6. Invariant: The region that doesn't contain objects must have only null values.
// validating/CircularQueueException.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
package validating;

public class CircularQueueException extends RuntimeException {
  public CircularQueueException(String why) {
    super(why);
  }
}
// validating/CircularQueue.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// 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
  private int 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);
  }
}

 Then we can create JUnit tests for the class:

// validating/tests/CircularQueueTest.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
package validating;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.*;

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]
*/

references:

1. On Java 8 - Bruce Eckel

2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/validating/CircularQueueException.java

3. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/validating/CircularQueue.java

猜你喜欢

转载自blog.csdn.net/wangbingfengf98/article/details/88917610