1 of 11

CSE 331�Software Design & Implementation

Spring 2026

Section 2 – Testing and Immutable Reasoning

2 of 11

Administrivia

  • HW1 will be released tonight and are due next Wednesday (4/15) @ 11:59pm!

2

3 of 11

Review - Testing Heuristics

≥ 2 Tests

Statement Coverage

  • Test every executable statement reachable by an allowed input

Branch Coverage

  • For every conditional, test all branches for allowed inputs

Loop Coverage

  • Every loop/recursive call must be tested on 0, 1, any 2+ iterations for allowed inputs

Exhaustive Testing

  • Test all possible inputs for functions with <= 10 allowed inputs

Notes on Testing Requirements

4 of 11

Review: JUnit Testing

  • What is JUnit?
    • JUnit is a framework that lets us easily develop tests in Java!
  • JUnit Testing Structure
    • JUnit tests are split into multiple methods, each with the @Test annotation.
    • There are other annotations like @Before, @BeforeEach, and more to reduce redundancy
    • Each test method is made up of assertions that compare the expected behavior of the program to the actual behavior

5 of 11

Review: JUnit Testing

Method Name

Method Description

assertTrue / assertFalse

Takes in a boolean and asserts that it is true / false

assertEquals / assertNotEquals

Takes in two objects and asserts that they are equal (using the .equals() method) / not equal

assertNull / assertNotNull

Takes in an object and asserts that it is null / not null

assertThrows / assertNotThrows

Given a method, assert that it will throw a certain exception / won’t throw one (Note: this requires a lambda to work)

For more information, check out the official documentation! https://docs.junit.org/6.0.3/overview.html

6 of 11

Reasoning with Immutable Code

  • Start with precondition
    • The precondition tells us what facts must be true at the very beginning of the method’s execution
  • Collecting facts
    • As we go through the code line-by-line, we must collect all known facts until we reach the return statement(s)
  • Implying the postcondition
    • Collected facts should imply the post condition to show the method implementation is correct

7 of 11

Reasoning With Immutable Code Example

/** Quadruples the value of x

* @requires x > 0

* @return a positive integer y

*/

public static int quadruple(int x) {

int y = 4 * x;

return y;

}

8 of 11

Reasoning With Immutable Code Example

  • At the return statement, we know these facts:
    • x > 0 and y = 4x
  • The desired postcondition is:
    • y > 0
  • As we can see, the known facts imply the postcondition since:

y = 4x

> 4(0)

= 0

  • Therefore, our code satisfies the postcondition

/** Quadruples the value of x

* @requires x > 0

* @return a positive integer y

*/

public static int quadruple(int x) {

int y = 4 * x;

return y;

}

9 of 11

Reasoning with Conditionals

  • When we have multiple branches, we must collect the facts at the end of every path!
  • Each of these paths should be consistent with the postcondition
  • Going into each conditional, you know everything before it and either
    • The condition in: if (condition) or
    • The negation of earlier branches and condition in: else if (condition) or
    • The negation of all earlier branches for: else
  • After all conditionals, you know the facts from the end of each branch
    • The postcondition should be true for each set of facts and combine to complete the postcondition

10 of 11

Reasoning with If Statements Example

/** Returns the absolute value of a given number x

* @return the integer y such that y = x if x >= 0 or y = -x

* if x < 0

*/

public static int abs(int x) {

if (x < 0) {

int y = -x;

return y; // Return #1

} else {

int y = x;

return y; // Return #2

}

}

11 of 11

Reasoning with If Statements Example

public static int abs(int x) {

if (x < 0) {

int y = -x;

return y; // Return #1

} else {

int y = x;

return y; // Return #2

}

}

  • At Return #1, we know these facts:
    • x < 0 and y = -x
  • At Return #2, we know these facts:
    • x >= 0 and y = x
  • The desired postcondition is:
    • (y = x if x >= 0) OR (y = -x if x < 0)
  • In the first path, we can see the postcondition holds.
  • In the second path, we can see the postcondition hold.
  • Since these paths are exhaustive, our code satisfies the postcondition