More Objects. Some Unit Testing.

More Objects. Some Unit Testing.
More Objects. Some Unit Testing.
Yoav Goldberg
Bar Ilan University
1/1
Last time
Object Oriented Programming in Java
I
I
Classes as blueprint for Objects.
Creating new classes.
I
I
I
Members
Constructors
Methods (and Access Methods)
I
How objects are represented in memory.
I
Monte-carlo PI example.
2/1
Today
More Object Oriented Code Example
Testing if Our Code Works
3/1
Today’s Code Example – The Card-game “War”
I
A Two players game.
I
Played with a standard set of cards.
I
At the beginning, the deck is shuffled, and each player gets
26 cards.
I
Then, at each turn, each player draws its top card.
The card with the higher rank wins (ace wins over others).
I
I
I
The winning player takes both cards into his winning pile.
In case both player draw same rank, we enter “war”.
I
I
I
Each player draws two more cards to the pile.
They then each draw another card, and the higher ranked
card wins the all of the pile.
In case of a tie, we enter another “war”.
I
If a player does not have enough cards, the other player
takes his cards and wins.
I
The game is over after K rounds, or when one player has
no more cards left.
4/1
Before We Start Coding
How do we know that our code is correct?
I
We must test it.
I
When do we test?
I
How do we test?
5/1
Before We Start Coding
Kinds of Tests
I
Unit Tests
I
I
Integration Tests
I
I
I
Verify that each unit (class) is working as it should.
Verify that the units work well together.
Verify that the code work together with other components,
such as Databses, servers. . .
Acceptance Tests
I
I
Software works end-to-end as intended.
Customer is happy.
6/1
Before We Start Coding
Let’s focus on Unit Testing
I
I
Each component you write should be tested.
Better test early than late.
I
It is much easier to find a bug in one component than to find
a bug in one of 5 or one of 20 components.
7/1
Before We Start Coding
Let’s focus on Unit Testing
I
I
Each component you write should be tested.
Better test early than late.
I
I
It is much easier to find a bug in one component than to find
a bug in one of 5 or one of 20 components.
Some people advocate writing tests before you write your
code.
I
I
This is called TDD (test-driven development)
Not a bad idea. Requires discipline.
7/1
A Concrete Advice
When Developing Code
I
Think of / implement tests.
I
Write some code.
I
Test it.
I
Write some more.
I
Test some more.
I
...
8/1
A Concrete Advice
When Developing Code
I
Think of / implement tests.
I
Write some code.
I
Test it.
I
Write some more.
I
Test some more.
I
...
What does it mean to test?
I
Write a “main” that instantiate your object(s).
I
Make them do things.
I
Write if / else to check if behavior is correct.
I
There are tools that can help (jUnit).
8/1
Testing Guidelines
Good tests are:
I
Isolated (one thing at a time).
I
Repeatable (expressed in code).
I
Have high coverage.
When writing a test:
I
I
Select one class (“object under test”)
Assume all the others are correct.
I
You can assume that because you have tested them!
9/1
Why Tests?
Confidence that your code works
10 / 1
Why Tests?
Confidence that your code works
Confidence to change your code
I
And know that you didn’t break anything.
10 / 1
Why Tests?
Confidence that your code works
Confidence to change your code
I
And know that you didn’t break anything.
Test Driven Design
I
Code that is easy to test is easy to use!
I
Always think: “How will I test this object/method?”
10 / 1
Before We Start Coding
Some Objects “Design” Criteria
I
Single Responsibility
I
Each Object/Class should do ONE main thing.
11 / 1
Before We Start Coding
Some Objects “Design” Criteria
I
Single Responsibility
I
I
Each Object/Class should do ONE main thing.
Query / Command Separation
I
I
I
Each Method should either return a value (query) OR
change the state (command).
If you change the state, return void.
“Convenience” methods that do both are fine, but they must
be super-simple – a sequence of a query and a command.
11 / 1
Writing the “War” Card Game.
12 / 1
Specification reminder
I
A Two players game.
I
Played with a standard set of cards.
I
At the beginning, the deck is shuffled, and each player gets
26 cards.
I
Then, at each turn, each player draws its top card.
The card with the higher rank wins (ace wins over others).
I
I
I
The winning player takes both cards into his winning pile.
In case both player draw same rank, we enter “war”.
I
I
I
Each player draws two more cards to the pile.
They then each draw another card, and the higher ranked
card wins the all of the pile.
In case of a tie, we enter another “war”.
I
If a player does not have enough cards, the other player
takes his cards and wins.
I
The game is over after K rounds, or when one player has
no more cards left.
13 / 1
Which classes do we need?
14 / 1
I
Card
I
Deck (a collection of 52 cards)
I
Player
I
Game
15 / 1
I
Card
I
Deck (a collection of 52 cards)
I
Player
I
Game
I
Pile
15 / 1
Which components are general? Which are game-specific?
16 / 1
Where should we start?
I
Game?
I
Card?
17 / 1
Where should we start?
I
Game?
I
Card?
I
something else?
17 / 1
Where should we start?
I
Game?
I
Card?
I
something else?
Both options are valid.
Today, we start with Card.
17 / 1
Card
I
What does a card do?
I
How are we going to use it?
18 / 1
Card
I
What does a card do?
I
How are we going to use it?
Imagine a usage:
Card c1 = new Card(12, "club");
Card c2 = new Card(1, "heart");
18 / 1
Card
I
What does a card do?
I
How are we going to use it?
Imagine a usage:
Card c1 = new Card(12, "club");
Card c2 = new Card(1, "heart");
I
but what if we wrote "hearts" by mistake?
I
or "Hearts"? or "hurts"?
18 / 1
Card
I
What does a card do?
I
How are we going to use it?
Imagine a usage:
Card c1 = new Card(12, "club");
Card c2 = new Card(1, "heart");
I
but what if we wrote "hearts" by mistake?
I
or "Hearts"? or "hurts"?
Another take:
Card c1 = new Card(12, Card.CLUB);
Card c2 = new Card(1, Card.HEART);
18 / 1
Card
public class Card {
public static final
public static final
public static final
public static final
int
int
int
int
DIAMOND = 1;
HEART = 2;
SPADE = 3;
CLUB = 4;
private int rank;
private int suit;
public Card(int rank, int suit) {
if (rank < 1 || rank > 13 || suit < 1 || suit > 4)
{
throw new RuntimeException("Bad Card
initialization value.");
}
this.rank = rank;
this.suit = suit;
}
}
19 / 1
Card
What else do we need?
I
Would be nice to be able to print the cards:
public class CardTest {
public static void main(String[] args) {
Card c1 = new Card(1, Card.DIAMOND);
Card c2 = new Card(9, Card.CLUB);
System.out.println(c1);
System.out.println(c2);
}
}
20 / 1
Card
What else do we need?
I
Would be nice to be able to print the cards:
public class CardTest {
public static void main(String[] args) {
Card c1 = new Card(1, Card.DIAMOND);
Card c2 = new Card(9, Card.CLUB);
System.out.println(c1);
System.out.println(c2);
}
}
I
Result:
Card@1b7c63f
Card@385715
20 / 1
What Just Happened?
I
We tried to print a card.
I
We got something out.
I
Q: Where did the value come from?
21 / 1
What Just Happened?
I
We tried to print a card.
I
We got something out.
I
Q: Where did the value come from?
I
A: From the default toString() method.
21 / 1
What Just Happened?
I
We tried to print a card.
I
We got something out.
I
Q: Where did the value come from?
I
A: From the default toString() method.
Remember,“everything is an object”
I
And objects have default behavior.
I
When printing an object, we need to get a String value.
I
So Java calls the object’s toString() method. Every object
has one.
I
We can override the object’s toString() and supply our
own.
21 / 1
Card
public class Card {
// ...
private static final String[] SUITE_NAMES =
{ "", "Diamond", "Heart", "Spade", "Club" };
public String toString() {
String stringRank = "";
if (this.rank == 1) {
stringRank = "Ace";
} else if (this.rank == 11) {
stringRank = "Prince";
} else if (this.rank == 12) {
stringRank = "Queen";
} else if (this.rank == 13) {
StringRank = "King";
} else { stringRank = String.valueOf(this.rank); }
String cardName = stringRank + " of "
+ Card.SUITE_NAMES[this.suit];
return cardName;
}
// ...
}
22 / 1
Card
public class CardTest {
public static void main(String[] args) {
Card c1 = new Card(1, Card.DIAMOND);
Card c2 = new Card(9, Card.CLUB);
System.out.println(c1);
System.out.println(c2);
}
}
Result:
Ace of Diamonds
9 of Clubs
23 / 1
Make the test more automatic
public class CardTest {
public static void main(String[] args) {
Card c1 = new Card(1, Card.DIAMOND);
Card c2 = new Card(9, Card.CLUB);
if (!c1.toString().equals("Ace of Diamonds")) {
System.out.println("Test 1 failed!");
}
if (!c2.toString().equals("9 of Clubs")) {
System.out.println("Test 2 failed!");
}
}
}
24 / 1
Make the test more automatic
public class CardTest {
public static void main(String[] args) {
Card c1 = new Card(1, Card.DIAMOND);
Card c2 = new Card(9, Card.CLUB);
assertEquals("Ace of Diamonds", c1.toString(), "
Card toString");
assertEquals("9 of Clubs", c2.toString(), "Card
toString");
}
public static void assertEquals(String s1, String s2,
String msg) {
if (!s1.equals(s2)) {
System.out.println("FAIL: " + msg + " expected
" + s1 + " and got " + s2);
}
}
}
25 / 1
Make the test more automatic
I
There are tools to help us automate test-writing.
I
In java, junit is a very good option.
I
We will not talk about it today.
26 / 1
Other Object Methods we Should Know
public String toString();
public boolean equals(Object other);
public int hashCode();
27 / 1
Other Object Methods we Should Know
public String toString();
public boolean equals(Object other);
public int hashCode();
hashCode() returns a number that should be unique to each object, but the
same to equal objects. We will learn more about it later, and you will also
learn about it in Data Structures in a month or so.
27 / 1
Back to the Game
28 / 1
Card
I
What about comparison to other cards?
I
Should it be in the Card class or somewhere else?
29 / 1
Deck
30 / 1
Deck
I
Create a deck with 52 cards.
I
Shuffle.
I
Take top card.
I
Number of cards, is empty.
30 / 1
Deck
I
Create a deck with 52 cards.
I
Shuffle.
I
Take top card.
I
Number of cards, is empty.
How about a “deal” method that will give cards to players?
30 / 1
Deck
I
Create a deck with 52 cards.
I
Shuffle.
I
Take top card.
I
Number of cards, is empty.
How about a “deal” method that will give cards to players?
. . . Single responsibility.
30 / 1
Dealer
31 / 1
Dealer
I
Deal cards
31 / 1
Pile
32 / 1
Pile
I
A collection of cards.
I
Can add or remove cards.
32 / 1
Pile
I
A collection of cards.
I
Can add or remove cards.
Should it just be a Stack, or an Array?
32 / 1
Pile
I
A collection of cards.
I
Can add or remove cards.
Should it just be a Stack, or an Array?
But what if we discover we need more functionality later?
32 / 1
Player
33 / 1
Player
I
Has playing cards.
I
Can play his top playing card.
I
Knows how many cards he’s got.
I
Can win new cards.
33 / 1
WarGame
34 / 1
WarGame
I
Initialize two players.
I
Give them cards.
I
Play game rounds.
I
Get winner.
34 / 1
WarGame
I
Initialize two players.
I
Give them cards.
I
Play game rounds.
I
Get winner.
Should handling of the game “logic” be done inside WarGame?
34 / 1
WarGame
I
Initialize two players.
I
Give them cards.
I
Play game rounds.
I
Get winner.
Should handling of the game “logic” be done inside WarGame?
Remember, single responsibility!
34 / 1
WarGameLogic
35 / 1
WarGameLogic
I
Playing a single “simple” round.
I
Playing a single “war” round.
35 / 1
WarGameLogic
I
Playing a single “simple” round.
I
Playing a single “war” round.
I
This piece is a bit complicated.
I
Let’s start with a test.
I
WarGameLogicTest.java
35 / 1
Summary
I
Object Design Criteria
I
I
I
Testing
I
I
I
I
Single Responsibility
Query vs. Command
Test often.
Try to make test repeatable.
Tests give you confidence!
The “War” card game example.
I
See complete code online.
36 / 1
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertising