You are on page 1of 41

2020-09-18

Advanced Object Oriented


Programming

EECS 2030
FA 2020 :: Section C

Advanced Object Oriented


Programming

EECS 2030
Lecture 3 :: Javadoc, Junit, recursion Junit Test,

1
2020-09-18

Java Basics – A quick recap

Types, Operators, Classes, Objects

Types
• What is a type?
▪ Set of values and valid operations that can be performed
with those values
o int: + - * / % == != >
o String: ==, equals, length, charAt, indexOf

▪ Primitive vs. Reference types

• Reference types include everything that is not primitive


▪ arrays []
▪ java.lang.String
▪ Collections (e.g. java.util.List,
java.util.ArrayList)
▪ User defined (class object Student, Range, Point)
4

2
2020-09-18

fixed representation in memory


5

Representations in Memory?

• Memory
▪ Primitive types (fixed allocation in memory)
o variable stores a value directly

▪ Reference types (dynamic allocation in memory)


o memory allocated at runtime usually
o reference stores a memory address initially (the location at
which a newly instantiated object will reside in memory when
allocated)

• Memory diagram
▪ Primitive vs. reference type representation
6

3
2020-09-18

Memory Diagrams
int a = 7;
Student s = new Student();

variable address value


name Store data or address
92
96
a 100 7
stack
s 104 1200a
108
...
1200 Student object heap
(GCH)
*we use an a to indicate a value is an a is an int which takes up 4 bytes in
address instead of a primitive numeric memory
value:
7 1200a means “the address 1200”

Memory Diagrams Another example


double x = -1.0;
int[] t = {1,2}; udent s = new Student();

variable address value


name

...
x 100 -1.0
stack
t 108 700a
...
700 Array object 1
heap
704 2 (GCH)
708
x is a double which takes up 8 bytes in
memory, and so…
Array is consecutive in memory, t is allocated the next available byte
8
occupying 2*4=8 bytes

4
2020-09-18

Object aliasing and pass-by-value

Basics
Accessors and Mutators
Anonymous objects
Object aliasing and pass-by-value

More on methods
object aliasing and call-by-value
public class MyInteger {
Imitate wrapper class
private int value; Integer

public MyInteger(int i) {
this.value = i;
}
MyInteger
public int getValue() {
return value; int value: 30
}

public void setValue(int value)


{
this.value = value;
}

public void toString()


{ return this.value + "";
10
}
10

5
2020-09-18

More on methods
object aliasing and call-by-value
MyInteger i = new MyInteger(30); i 60 600a
MyInteger j = i; j 600a
System.out.println(i.getValue()); // ? 30
System.out.println(j.getValue()); // ? 30

j.setValue(100);
System.out.println(i.getValue()); // ? 100
System.out.println(j.getValue()); // ? 100 600 MyInteger
value object

30 100
System.out.println(j==i); // ? True
System.out.println(j.equals(i)); // ?
Heap
(GCH)
i
30
100
j
11

11

More on methods
object aliasing and call-by-value
arrays
a 60 600a
int[] a = {10,20,30}; b 600a
int[] b = a;
System.out.println(Arrays.toString(a)); // ?
System.out.println(Arrays.toString(b)); // ?
10 20 30
10 20 30

600 10
b[1] = 200; // address 600+4 604 20 200
System.out.println(Arrays.toString(a)); // ?
System.out.println(Arrays.toString(b)); // ? 608 30
10 200 30 Heap
System.out.println(j==i); // ? 10 200 30
(GCH)
System.out.println(j.equals(i)); // ?
a
10 20 30
200
b
12

12

6
2020-09-18

More on methods
object aliasing and call-by-value
• aliasing describes a situation in which a data location (Java: object)
in memory can be accessed through different symbolic names (Java:
reference variables) in the program.
• Thus, modifying the data (object) through one name (reference
variables) implicitly modifies the values associated with all aliased
names (variables), which may or may not be expected by the
programmer. (more later)

13
reference variables

13

More examples on aliasing


int a = 1;
int b = 2;
int c = 3;
int[] numbers1 = {a, b, c};
int[] numbers2 = new int[numbers1.length];

for(int i = 0; i < numbers1.length; i ++) {


numbers2[i] = numbers1[i];
}

numbers1[0] = 4;

System.out.println(Arrays.toString(numbers1)); //? 4 2 3
System.out.println(Arrays.toString(numbers2)); //? 1 2 3

Is there any Aliasing?


14 Top level or element level?

14

7
2020-09-18

More examples on aliasing

int a = 1;
int b = 2;
int c = 3;
int[] numbers1 = {a, b, c};
int[] numbers2 = numbers1;

numbers1[0] = 4;

System.out.println(Arrays.toString(numbers1)); //? 4 2 3
System.out.println(Arrays.toString(numbers2)); //? 4 2 3

Is there any Aliasing?


Top level or element level?

15

15

More examples on aliasing


MyInteger[] numbers1 = {new MyInteger(1), new
MyInteger(2), new MyInteger(3)};
MyInteger[] numbers2 = new MyInteger[numbers1.length];

for(int i = 0; i < numbers1.length; i ++) {


numbers2[i] = numbers1[i];
}

numbers1[0].setValue(4);

System.out.println(Arrays.toString(numbers1)); //? 4 2 3
System.out.println(Arrays.toString(numbers2)); //? 4 2 3

Is there any Aliasing?


16 Top level or element level?

16

8
2020-09-18

More examples on aliasing


MyInteger[] numbers1 = {new MyInteger(1), new
MyInteger(2), new MyInteger(3)};
MyInteger[] numbers2 = numbers1;

numbers1[0].setValue(4);

System.out.println(Arrays.toString(numbers1)); //? 4 2 3
System.out.println(Arrays.toString(numbers2)); //? 4 2 3

Is there any Aliasing?


17 Top level or element level?

17

Object aliasing and pass-by-value

Basics
Accessors and Mutators
Anonymous objects
Object aliasing and pass-by-value

18

18

9
2020-09-18

Pass-by-value with primitive types


the value of a
is passed to the
client method
int a = 3; Doubler.twice
a 60 3
Doubler.twice(a);
System.out.println(a);

// tries to double x
this is a different
public static void twice (int x) Doubler.twice x = a;
{ method than the
x = 2 * x; previous example
} int x = a; (now resides at
address 800)
x = 2 * x;
800 Doubler.twice

x 3
a 3 parameter x
is an independent
copy of the value
19 x 3 of argument a
(a primitive)

19

Pass-by-value with primitive types


the value of a
a not changed is passed to the
client method
int a = 3; Doubler.twice
a 60 3
Doubler.twice(a);
System.out.println(a);

// tries to double x
this is a different
public static void twice (int x) Doubler.twice x = a;
{ method than the
x = 2 * x; previous example
} int x = a; (now resides at
address 800)
x = 2 * x;
800 Doubler.twice

x 3 6
a 3 parameter x
is an independent
copy of the value
20 x 6 of argument a
(a primitive)

20

10
2020-09-18

Pass-by-value with reference types


MyInteger b = the value of b
is passed to the
new MyInteger(3); method
client
Doubler.twice(b); Doubler.twice
b 60 500a
b.getValue();

// tries to double x
public static void twice (MyInteger x) { 500 MyInteger
int i = x.getValue(); object
x.setValue( 2 * i ); x = b;
value 3
}
Call-by
MyInteger x = b;
int i = x.getValue() value
x.setX(2*i)
aliasing Doubler.twice
600
b x 500a
parameter x
3
is an independent
copy of the value
21
x of argument b
(a reference)
21

Pass-by-value with reference types


MyInteger b = object changed the value of b
is passed to the
new MyInteger(3); method
client
Doubler.twice(b); Doubler.twice
b 60 500a
b.getValue(); 6

// tries to double x
public static void twice (MyInteger x) { 500 MyInteger
int i = x.getValue(); object
x.setValue( 2 * i ); x = b;
value 3 6
}
Call-by
MyInteger x = b;
int i = x.getValue() value
x.setX(2*i)

600 Doubler.twice

b x 500a
parameter x
6
is an independent
copy of the value
22
x of argument b
(a reference)
22

11
2020-09-18

Pass-by-value with reference types


array
int [] b = {10,20,30} the value of b
is passed to the
Doubler.twice(b); method
client
Doubler.twice
b 60 500a

// tries to double x
public static void twice (int[] x) {
x[1] = x[1]*2;
} 500 10
int[] x = b; value 20 x = b;
x[1] = x[1]*2;
30 Call-by
value

600 Doubler.twice

b x 500a
10 20 30 parameter x
is an independent
copy of the value
23
x of argument b
(a reference)
23

Pass-by-value with reference types


Array object changed
int [] b = {10,20,30} the value of b
is passed to the
Doubler.twice(b); method
client
Doubler.twice
b 60 500a

// tries to double x
public static void twice (int[] x) {
x[1] = x[1]*2;
} 500 10
int[] x = b; value 20 40 x = b;
x[1] = x[1]*2;
30 Call-by
value

600 Doubler.twice

b x 500a
10 20 30 parameter x
is an independent
40 copy of the value
24
x of argument b
(a reference)
24

12
2020-09-18

Primitive data type


public class Doubler {

private Doubler() {
}

// tries to double x
public static void twice (int x) {
x = 2 * x; int a = 3;
} Doubler.twice(a);
System.out.println(a);
// tries to double x
public static int twice (int x) {
int i = 2 * x;
return i;
}
int a = 3;
}
a = Doubler.twice(a);
System.out.println(a); // 6
25

25

public class Doubler {

private Doubler() {
}

// tries to double x
public static void twice (int x) {
x = 2 * x;
}

// tries to double x
public static void twice (MyInteger x) {
int i = x.getValue();
x = new MyInteger(2 * i );
}
}

What will happen?


26

26

13
2020-09-18

Function call flows

Basics
Accessors and Mutators
Anonymous objects
Object aliasing and pass-by-value

27

27

static void A ()
{
A_statement1;
B();
A_statement2; static void B ()
} {
B_statement1;
C();
B_statement2;
}

A(); static void C ()


System.out.println("Done"); {
C_stetement1;
D();
C_statement2;
}

static void D ()
{
D_statement1;
D_statement2;
}

28

28

14
2020-09-18

A()

100 main method

a A()

600 statememt_1
A()
A method B()
main()
statement_2
29
call/execution/program stack

29

A()

100 main method

a A()

750 statememt_1

B method C()

statement_2

B() 600 statememt_1


A()
A method B()
main()
statement_2
30
call/execution/program stack

30

15
2020-09-18

A()

100 main method

a A()
800 statememt_1

C method D()

statement_2

750 statememt_1

B method C()

statement_2

C()
B() 600 statememt_1
A()
A method B()
main()
statement_2
31
call/execution/program stack

31

950 statememt_1
A()
D method statement_2

100 main method

a A()
800 statememt_1

C method D()

statement_2

750 statememt_1

B method C()

statement_2
D()
C()
B() 600 statememt_1
A()
A method B()
main()
statement_2
32
call/execution/program stack

32

16
2020-09-18

A()

100 main method

a A()
800 statememt_1

C method D()

statement_2

750 statememt_1

B method C()

statement_2

C()
B() 600 statememt_1
A()
A method B()
main()
statement_2
33
call/execution/program stack

33

A()

100 main method

a A()

750 statememt_1

B method C()

statement_2

B() 600 statememt_1


A()
A method B()
main()
statement_2
34
call/execution/program stack

34

17
2020-09-18

A()

100 main method

a A()

600 statememt_1
A()
A method B()
main()
statement_2
35
call/execution/program stack

35

A()

100 main method

a A()

main()

36
call/execution/program stack

36

18
2020-09-18

Can a function call itself?


What happens if it can?
static void A ()
{
A_statement1;
A();
A_statement2;
}

37
call/execution/program stack

37

static void A () A function call itself (recursive call)


{ • Possible
A_statement1; • With care
A();
A_statement2; static void A ()
} {
A_statement1;
A();
A_statement2;
}

A(); static void A ()


System.out.println("Done"); {
A_stetement1;
A();
A_statement2;
}

static void A () static void A ()


{ {
A_statement1; A_statement1;
A() A()
A_statement2; A_statement2;
} }
38

38

19
2020-09-18

A()

100 main method

a A()

600 statememt_1
A()
A method A()
main()
statement_2
39
call/execution/program stack

39

A()

100 main method

a A()

750 statememt_1

A method A()

statement_2

A() 600 statememt_1


A()
A method A()
main()
statement_2
40
call/execution/program stack

40

20
2020-09-18

A()

100 main method

a A()
800 statememt_1

A method A()

statement_2

750 statememt_1

A method A()

statement_2

A()
A() 600 statememt_1
A()
A method A()
main()
statement_2
41
call/execution/program stack

41

950 statememt_1
A()
A method A()

statement_2
100 main method

a A()
800 statememt_1

A method A()

statement_2

750 statememt_1

A method A()

statement_2
A()
A()
A() 600 statememt_1
A()
A method A()
main()
statement_2
42
call/execution/program stack

42

21
2020-09-18

950 statememt_1
A()
A method A()

statement_2
100 main method

a A()
800 statememt_1

A method A()

statement_2

Eventually, “stack overflow”


A() 750 statememt_1

A() A method A()


A() statement_2
A()
A()
A() 600 statememt_1
A()
A method A()
main()
statement_2
43
call/execution/program stack

43

Documenting

Javadoc

44

44

22
2020-09-18

Design by Contract (DbC)

• Separation of Concerns
o CLIENT vs. IMPLEMENTER

• In this course we focus on implementing classes:


▪ For Clients to use…
▪ In so, must consider what constitutes the “contract” between
client and implementer
▪ This is typically established through pre/post-conditions,
and API documentation

45

45

preconditions and postconditions

the meaning of method pre- and postconditions:

• precondition
▪ a condition that the client must ensure is true immediately
before a method is invoked

• postcondition
▪ a condition that the method must ensure is true immediately
after the method is invoked

double division(double numerator, double denominator)

double sqrtRoot(double i)
46

46

23
2020-09-18

Preconditions

• a condition that the client must ensure is true immediately


before invoking a method
▪ if the precondition is not true, then the client has no
guarantees of what the method will do

• for methods, preconditions are conditions on the values of


the arguments passed to the method
▪ you need to carefully read the API to discover the
preconditions

double division(double numerator, double denominator)

double sqrtRoot(double i)
47

47

Postconditions

• a method postcondition is a condition that the method must


ensure is true immediately after the method is invoked
▪ if the postcondition is not true, then there is something
wrong with the implementation of the method

• for methods, postconditions are:


▪ conditions on the arguments after the method finishes
▪ conditions on the return value

double division(double numerator, double denominator)

double sqrtRoot(double i)
48

48

24
2020-09-18

Documenting

• documenting code was not a new idea when Java was


invented
▪ however, Java was the first major language to embed
documentation in the code and extract the documentation
into readable electronic APIs

• the tool that generates API documents from comments


embedded in the code is called Javadoc

49

49

1. Generate “doc document”

2. Invoke Javadoc tool

50

50

25
2020-09-18

Documenting
• Javadoc processes doc comments that immediately precede a
class, attribute, constructor or method declaration
▪ doc comments delimited by /** and */
▪ doc comment written in HTML and made up of two parts
1. a description
first sentence of description gets copied to the summary section
only one description block; can use <p> to create separate paragraphs

2. block tags
begin with @
@param
@return
@throws
….
@pre. (a non-standard (custom tag used in EECS2030) for documenting
51
preconditions)

51

Method documentation example


• Eclipse will generate an empty Javadoc comment for you if you
▪ type /** and enter. Or,
▪ right-click on the class/field/constructor/method header line and
choose Source → Generate Element Comment

52

52

26
2020-09-18

Method documentation example


• Eclipse will generate an empty Javadoc comment for you if you
right-click on the class/field/constructor/method header and choose
Source → Generate Element Comment

/**
* @param min
* @param max
* @param value
* @return
*/

public static boolean isBetween(int min, int max, int value) {


// implementation not shown
}

53

53

Method documentation example


The first sentence of the documentation should be short summary of the
method; this sentence appears in the constructor/method summary section.

/**
* Returns true if value is strictly greater than min and strictly
* less than max, and false otherwise.
*
* @param min
* @param max
* @param value
* @return
*/
public static boolean isBetween(int min, int max, int value) {
// implementation not shown
}

54

54

27
2020-09-18

Method documentation example


You should provide a brief description of each parameter.

/**
* Returns true if value is strictly greater than min and strictly
* less than max, and false otherwise.
*
* @param min a minimum value
* @param max a maximum value
* @param value a value to check
* @return
*/
public static boolean isBetween(int min, int max, int value) {
// implementation not shown
}

55

55

Method documentation example


Provide a brief description of the return value if the return type is not
void. This description often describes a postcondition of the method.

/**
* Returns true if value is strictly greater than min and strictly
* less than max, and false otherwise.
*
* @param min a minimum value
* @param max a maximum value
* @param value a value to check
* @return true if value is strictly greater than min and strictly
* less than max, and false otherwise
*/
public static boolean isBetween(int min, int max, int value) {
// implementation not shown
}

56

56

28
2020-09-18

Method documentation example


Describe any preconditions using the EECS2030 specific
@pre. tag. You have to manually do this.
/**
* Returns true if value is strictly greater than min and strictly
* less than max, and false otherwise.
*
* @param min a minimum value
* @param max a maximum value
* @param value a value to check
* @return true if value is strictly greater than min and strictly
* less than max, and false otherwise
* @pre. min is greater than or equal to max
*/
public static boolean isBetween(int min, int max, int value) {
// implementation not shown
}

57

57

Method documentation example


• if a method throws an exception then you should use the
@throws tag to document the exception
/**
* Given a list containing exactly 2 integers, returns the smaller of the
* two integers. The list <code>t</code> is not modified by this method.
* For example:
*
* <pre>
* t Test2F.min2(t)
* ---------------------------
HTML markup is also allowed
* [-5, 9] -5
* [3, 3] 3
* [12, 6] 6
* </pre>
*
* @pre t is not null, and contains 2 integers
* @param t a list containing exactly 2 integers
* @return the minimum of the two values in t
* @throws IllegalArgumentException if the list does not contain exactly 2
* integers
*/
public static int min2(List<Integer> t) {
}
58
58

29
2020-09-18

Generating document API


• red 200% javadoc Hello.java
….

• Eclipse

59

59

• Lab0 screeshot

60

60

30
2020-09-18

61

61

Javadoc -- more examples

• every public field should have a Javadoc comment that


describes the purpose of the field

• every public constructor should have a Javadoc comment that


describes the purpose of the constructor
• every public method should have a Javadoc comment that
describes the purpose of the method
• ……

Self-study: Read slides 108 to 127 from


last lecture

62

62

31
2020-09-18

Testing

JUnit

63

63

Testing

• Testing code is a vital part of the development process


• The goal of testing is to find defects in your code
▪ Program testing can be a very effective way to show the
presence of bugs, but it is hopelessly inadequate for
showing their absence.
— Edsger W. Dijkstra

64

64

32
2020-09-18

Testing with a main() method


• If I had asked you to test a method, the naïve approach would be
to just create a main method in a client program..

• Imagine you are testing the following methods in the static class
eecs2030.testing.Hello

static int sum(int a, int b) // returns the sum of two ints

static double avg(double a,double b, double c)


// returns average of a,b,c

static void swap2(List t) // swaps 1st & 2nd element of list t

▪ toInt(t) // converts a list of ints to a single int

65

65

public static void main(String[] args) {


// sum
int a = 1;
int b = 1;
int c = 1;
int sum = Test.sum(a,b);
System.out.println(
String.format(“sum of %d and %d: ", a, b) + sum) );

// avg
System.out.println(
String.format("average of %d, %d, and %d: ", a, b, c) +
Test.avg(a, b, c));

// swap2
List<Integer> t = new ArrayList<Integer>();
t.add(3);
t.add(5);
String s = t.toString();
Test.swap2(t);
System.out.println(
String.format("swap2(%s): %s", s, t.toString()));
66

66

33
2020-09-18

Testing with a main method

• running the main method results in the following output:

sum of 1 and 1: 2

average of 1, 1, and 1: 1.0

swap2([3, 5]): [5, 3]


toInt([1, 2, 3]) : 123

67

67

Testing with a main method

• testing using a single main() method has some


disadvantages:
▪ someone has to examine the output by eye to determine if
the tests have passed or failed

▪ all of the tests are in one method


o we can’t run tests independently from one another
o there is no easy way to pick which tests we want to run

68

68

34
2020-09-18

JUnit

• JUnit is a unit test framework in Java


▪ unittest module in Python

• “A framework is a semi-complete application. A framework


provides a reusable, common structure to share among
applications.”
▪ from the book JUnit in Action

69

69

Unit test
• “A unit test examines the behavior of a distinct unit of
work. Within a Java application, the “distinct unit of work”
is often (but not always) a single method. … A unit of work
is a task that isn't directly dependent on the completion of
any other task.”
▪ from the book JUnit in Action

70

70

35
2020-09-18

Junit Framework?
• Automate the testing of correctness of your Java classes.

• Once you derive the list of tests, translate it into a JUnit test case,
which is just a Java class that you can execute upon.

• Not only to confirm when your implementation is correct, but also to


reveal errors when your implementation is incorrect

• JUnit tests are helpful callers/clients of your classes, where each


test may
▪ attempts to use a method in a legal way (i.e., satisfying its
precondition), and report:
o Success if the result is as expected
o Failure if the result is not as expected

▪ also attempt to use a method in an illegal way (i.e., not


satisfying its precondition), and report:
o Success if the expected exception occurs.
71 o Failure if the expected exception does not occur.

71

A JUnit test example

• let’s write a test for the method sum, avg, swap2


▪ we need a class to write the test in
▪ we need to import the JUnit library
▪ we need to write a method that implements the test

• happily, Eclipse helps you do all of this


▪ in the Package Explorer, right click on the class that you
want to test and select New > JUnit Test Case

72

72

36
2020-09-18

73

73

74

74

37
2020-09-18

package eecs2030.testing;

import static org.junit.Assert.*; static import: allows you to use


import org.junit.Test; static methods from the class
org.junit.Assert without specifying
the class name
public class HelloTest {
Avoid the widespread use of static
@Test imports. Although it is convenient
public void test () { being able to not include the class
name in front of the method name,
fail("Not yet implemented");intit makes
a = -99;
it difficult to tell which
} class the method comes from*.

org.junit.Assert.fail("Not yet implemented");


org.junit.Assert.assertEquals(…)

75 *https://docs.oracle.com/javase/8/docs/technotes/guides/language/static-import.html

75

package eecs2030.testing;

import static org.junit.Assert.*;


import org.junit.Test;

public class HelloTest {

@Test An annotation; JUnit uses the @Test


annotation to determine which
public void test () {
methods are unit tests.
fail("Not yet implemented");
}

76

76

38
2020-09-18

package eecs2030.testing;

import static org.junit.Assert.*;


import org.junit.Test;

public class HelloTest {

@Test
public void test_sum() {
int a = 1;
int b = 1;
int expected = 2;
int actual = Hello.sum(a, b); // call static method
Use a Junit built-in method to test if expected and actual
} are equal/same
The JUnit method throws an exception if expected and actual
are not equal. JUnit handles the exception and reports the test
failure to the user.

77

77

Common JUnit assertion methods


http://junit.sourceforge.net/javadoc/
assertTrue(Boolean condition) fails if the boolean test is false
assertFalse(Boolean condition) fails if the boolean test is true
assertEquals(expected, actual) fails if the values are not equal
assertNotEquals(expected, actual) fails if the values are equal
assertArrayEquals(expected, actual) fails if the values are not equal
assertSame(expected, actual) fails if the values are not the same (by ==)
assertNotSame(expected, actual) fails if the values are the same (by ==)
assertNull(value) fails if the given value is not null
assertNotNull(value) fails if the given value is null
fail() causes current test to immediately fail
• All are static void
• Return nothing if pass assertation
• Throw exception if not pass assertation, failing the test

• Each method can also be passed a string to display if it fails:


78▪ e.g. assertEquals("not same", expected, actual)
assertTrue ("not true", expected, actual) overloaded

78

39
2020-09-18

• assertEquals: int, double, long, Object


▪ for primitive data, assertEquals, assertSame are same uses ==
▪ for reference data, assertEquals uses equals(), assertSame uses ==
▪ double:
uses assertEquals(double expected, double actual, double elsilon)

import static org.junit.Assert.*;


import org.junit.Test;

public class HelloTest {


@Test
public void test_sum() {
int a = 1;
int b = 1;
int expected = 2;
int actual = Hello.sum(a, b);
assertEquals(expected, actual);
or
assertSame(expected, actual);
or
assertTrue(expected == actual);
79
}

79

• assertEquals: int, double, long, Object


▪ for primitive data, assertEquals, assertSame are same uses ==
▪ for reference data, assertEquals uses equals(), assertSame uses ==
▪ double:
uses assertEquals(double expected, double actual, double elsilon)

@Test
public void test_swap2() {
List<Integer> actual = new ArrayList<Integer>();
actual.add(-99);
actual.add(88);
List<Integer> expected = new ArrayList<Integer>();
expected.add(88);
expected.add(-99);
Hello.swap2(actual);
assertEquals(expected, actual);
// or
assertTrue(expected.equals(actual));
}
80 assertSame(expected, actual)

80

40
2020-09-18

Run testcases

81

81

82

82

41

You might also like