> For the complete documentation index, see [llms.txt](https://emory.gitbook.io/dsa-java/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://emory.gitbook.io/dsa-java/priority-queues/unit-testing.md).

# 2.3. Unit Testing

Robustness tests.

## Auxiliary Method

Let us create [`PriorityQueueTest`](https://github.com/emory-courses/dsa-java/blob/master/src/test/java/edu/emory/cs/queue/PriorityQueueTest.java) and define `testRobustnessAux()` that checks the robustness of any PQ inheriting `AbstractPriorityQueue`:

{% code lineNumbers="true" %}

```java
/**
 * @param pq   a priority queue.
 * @param keys a list of comparable keys.
 * @param comp a comparator used for sorting.
 */
<T extends Comparable<T>> void testRobustness(AbstractPriorityQueue<T> pq, List<T> keys, Comparator<T> comp) {
    keys.forEach(pq::add);
    keys = keys.stream().sorted(comp).collect(Collectors.toList());
    keys.forEach(key -> assertEquals(key, pq.remove()));
}
```

{% endcode %}

* `L6`: the generic type `T` is defined specifically for this method such that the priority queue `pq`, the list `keys`, and the comparator `comp` take the same type `T` that is comparable.
* `L7`: any collection that inherits the interface [`Iterable`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Iterable.html) has the member method [`forEach()`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Iterable.html#forEach\(java.util.function.Consumer\)) that takes a [`Consumer`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/function/Consumer.html)  and applies each key in the collection to the consumer.
* `L8`: any collection has the member method [`stream()`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/Collection.html#stream\(\)) that returns the [`Stream`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/stream/Stream.html) of the collection.
  * [`sorted()`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/stream/Stream.html#sorted\(java.util.Comparator\)): creates a stream of the collection whose keys are sorted
  * [`collect()`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/stream/Stream.html#collect\(java.util.stream.Collector\)): creates a collection specified by the [`Collector`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/stream/Collector.html).
  * [`toList()`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/stream/Collectors.html#toList\(\)): returns a collector that transforms the stream into a list.
* `L9`: iterates each of the sorted keys and compares it to the returned value of `pq.remove()`.

> What are the advantages of defining a method-level generic type?

## Functional Programming

The following code shows a traditional way of iterating over a list (that is equivalent to `L7` above):

```java
for (int i=0; i<keys.size(); i++)
    pq.add(keys.get(i));
```

Java 5 introduced an enhanced for loop that simplified the traditional for loop:

```java
for (T key : keys)
    pq.add(key);
```

Java 8 introduced [lambda expressions](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html) that enabled functional programming in Java.  The following code takes each `key` (as a variable) in `keys` and applies it to `pq.add()`:

```java
keys.forEach(key -> pq.add(key));
```

The syntax of the above code can be simplified as follows (as shown in `L7`):

```java
keys.forEach(pq::add);
```

> What are the main differences between object-oriented programming and functional programming?

{% hint style="info" %}
Since Java 8, higher-order methods can be defined by parameterizing types of interfaces in the [function](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/function/package-summary.html) package.
{% endhint %}

## Test: Robustness

Let us define the `testRobustness()` method that calls the auxiliary method `testRobustnessAux()`:

{% code lineNumbers="true" %}

```java
@Test
public void testRobustness() {
    List<Integer> keys = List.of(4, 1, 3, 2, 5, 6, 8, 3, 4, 7, 5, 9, 7);
    Comparator<Integer> natural = Comparator.naturalOrder();
    Comparator<Integer> reverse = Comparator.reverseOrder();

    testRobustness(new LazyPriorityQueue<>(), keys, reverse);
    testRobustness(new EagerPriorityQueue<>(), keys, reverse);
    testRobustness(new BinaryHeap<>(), keys, reverse);

    testRobustness(new LazyPriorityQueue<>(reverse), keys, natural);
    testRobustness(new EagerPriorityQueue<>(reverse), keys, natural);
    testRobustness(new BinaryHeap<>(reverse), keys, natural);
}
```

{% endcode %}

* `L7-9`: tests different types of max-PQs. The keys need to be sorted in reverse order for it to test the `remove()` method.
* `L11-13`: tests different types of min-PQs. The keys need to be sorted in the natural order for it to test the `remove()` method.

> The generic types of the PQs in `L4-5` are explicitly coded as `<Integer>`, whereas they are simplified to `<>` in  `L7-13`.  When do generic types need to be explicitly coded?&#x20;

{% hint style="info" %}
The `testRobustness()` method illustrates the benefit of defining `AbstractPriorityQueue` such that any type of PQ can be passed to `testRobustnessAux()` for unit-testing.
{% endhint %}
