Skip to content

Commit 342a403

Browse files
committed
Add unit tests
1 parent ae98f17 commit 342a403

File tree

9 files changed

+300
-13
lines changed

9 files changed

+300
-13
lines changed

update-method/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@
3333
<modelVersion>4.0.0</modelVersion>
3434

3535
<artifactId>update-method</artifactId>
36+
<dependencies>
37+
<dependency>
38+
<groupId>junit</groupId>
39+
<artifactId>junit</artifactId>
40+
</dependency>
41+
</dependencies>
3642

3743

3844
</project>

update-method/src/main/java/com/iluwatar/updatemethod/App.java

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,37 @@
2323

2424
package com.iluwatar.updatemethod;
2525

26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
28+
29+
/**
30+
* This pattern simulate a collection of independent objects by telling each to
31+
* process one frame of behavior at a time. The game world maintains a collection
32+
* of objects. Each object implements an update method that simulates one frame of
33+
* the object’s behavior. Each frame, the game updates every object in the collection.
34+
*/
2635
public class App {
2736

37+
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
38+
39+
/**
40+
* Program entry point.
41+
* @param args runtime arguments
42+
*/
2843
public static void main(String[] args) {
29-
var world = new World();
30-
var skeleton1 = new Skeleton(1, 10);
31-
var skeleton2 = new Skeleton(2, 70);
32-
var statue = new Statue(3, 20);
33-
world.addEntity(skeleton1);
34-
world.addEntity(skeleton2);
35-
world.addEntity(statue);
36-
world.gameLoop();
44+
try {
45+
var world = new World();
46+
var skeleton1 = new Skeleton(1, 10);
47+
var skeleton2 = new Skeleton(2, 70);
48+
var statue = new Statue(3, 20);
49+
world.addEntity(skeleton1);
50+
world.addEntity(skeleton2);
51+
world.addEntity(statue);
52+
world.run();
53+
Thread.sleep(200);
54+
world.stop();
55+
} catch (InterruptedException e) {
56+
LOGGER.error(e.getMessage());
57+
}
3758
}
3859
}

update-method/src/main/java/com/iluwatar/updatemethod/Entity.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
import org.slf4j.Logger;
2727
import org.slf4j.LoggerFactory;
2828

29+
/**
30+
* Abstract class for all the entity types.
31+
*/
2932
public abstract class Entity {
3033

3134
protected final Logger logger = LoggerFactory.getLogger(this.getClass());

update-method/src/main/java/com/iluwatar/updatemethod/Skeleton.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323

2424
package com.iluwatar.updatemethod;
2525

26+
/**
27+
* Skeletons are always patrolling on the game map. Initially all the skeletons
28+
* patrolling to the right, and after them reach the bounding, it will start
29+
* patrolling to the left. For each frame, one skeleton will move 1 position
30+
* step.
31+
*/
2632
public class Skeleton extends Entity {
2733

2834
private static final int PATROLLING_LEFT_BOUNDING = 0;
@@ -31,11 +37,22 @@ public class Skeleton extends Entity {
3137

3238
protected boolean patrollingLeft;
3339

40+
/**
41+
* Constructor of Skeleton.
42+
*
43+
* @param id id of skeleton
44+
*/
3445
public Skeleton(int id) {
3546
super(id);
3647
patrollingLeft = false;
3748
}
3849

50+
/**
51+
* Constructor of Skeleton.
52+
*
53+
* @param id id of skeleton
54+
* @param postition position of skeleton
55+
*/
3956
public Skeleton(int id, int postition) {
4057
super(id);
4158
this.position = position;
@@ -55,7 +72,7 @@ public void update() {
5572
patrollingLeft = true;
5673
}
5774
}
58-
logger.info("Skeleton " + id + " is on position " + position);
75+
logger.info("Skeleton " + id + " is on position " + position + ".");
5976
}
6077
}
6178

update-method/src/main/java/com/iluwatar/updatemethod/Statue.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,32 @@
2323

2424
package com.iluwatar.updatemethod;
2525

26+
/**
27+
* Statues shoot lightning at regular intervals.
28+
*/
2629
public class Statue extends Entity {
2730

2831
protected int frames;
2932

3033
protected int delay;
3134

35+
/**
36+
* Constructor of Statue.
37+
*
38+
* @param id id of statue
39+
*/
3240
public Statue(int id) {
3341
super(id);
3442
this.frames = 0;
3543
this.delay = 0;
3644
}
3745

46+
/**
47+
* Constructor of Statue.
48+
*
49+
* @param id id of statue
50+
* @param delay the number of frames between two lightning
51+
*/
3852
public Statue(int id, int delay) {
3953
super(id);
4054
this.frames = 0;
@@ -50,6 +64,6 @@ public void update() {
5064
}
5165

5266
private void shootLightning() {
53-
logger.info("Statue " + id + " is shooting lightning!");
67+
logger.info("Statue " + id + " shoots lightning!");
5468
}
5569
}

update-method/src/main/java/com/iluwatar/updatemethod/World.java

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,33 +25,88 @@
2525

2626
import java.util.ArrayList;
2727
import java.util.List;
28+
import java.util.Random;
2829

30+
import org.slf4j.Logger;
31+
import org.slf4j.LoggerFactory;
32+
33+
/**
34+
* The game world class. Maintain all the objects existed in the game frames.
35+
*/
2936
public class World {
3037

38+
private static final Logger LOGGER = LoggerFactory.getLogger(World.class);
39+
3140
private List<Entity> entities;
3241

42+
private volatile boolean isRunning;
43+
3344
public World() {
3445
entities = new ArrayList<>();
46+
isRunning = false;
3547
}
3648

37-
public void gameLoop() {
38-
while (true) {
49+
/**
50+
* Main game loop. This loop will always run until the game is over. For
51+
* each loop it will process user input, update internal status, and render
52+
* the next frames. For more detail please refer to the game-loop pattern.
53+
*/
54+
private void gameLoop() {
55+
while (isRunning) {
3956
processInput();
4057
update();
4158
render();
4259
}
4360
}
4461

45-
private void processInput() {}
62+
/**
63+
* Handle any user input that has happened since the last call. In order to
64+
* simulate the situation in real-life game, here we add a random time lag.
65+
* The time lag ranges from 50 ms to 250 ms.
66+
*/
67+
private void processInput() {
68+
try {
69+
int lag = new Random().nextInt(200) + 50;
70+
Thread.sleep(lag);
71+
} catch (InterruptedException e) {
72+
LOGGER.error(e.getMessage());
73+
}
74+
}
4675

76+
/**
77+
* Update internal status. The update method pattern invoke udpate method for
78+
* each entity in the game.
79+
*/
4780
private void update() {
4881
for (var entity : entities) {
4982
entity.update();
5083
}
5184
}
5285

86+
/**
87+
* Render the next frame. Here we do nothing since it is not related to the
88+
* pattern.
89+
*/
5390
private void render() {}
5491

92+
/**
93+
* Run game loop.
94+
*/
95+
public void run() {
96+
LOGGER.info("Start game.");
97+
isRunning = true;
98+
var thread = new Thread(this::gameLoop);
99+
thread.start();
100+
}
101+
102+
/**
103+
* Stop game loop.
104+
*/
105+
public void stop() {
106+
LOGGER.info("Stop game.");
107+
isRunning = false;
108+
}
109+
55110
public void addEntity(Entity entity) {
56111
entities.add(entity);
57112
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* The MIT License
3+
* Copyright © 2014-2019 Ilkka Seppälä
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
24+
package com.iluwatar.updatemethod;
25+
26+
import org.junit.Test;
27+
28+
public class AppTest {
29+
30+
@Test
31+
public void testMain() {
32+
String[] args = {};
33+
App.main(args);
34+
}
35+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* The MIT License
3+
* Copyright © 2014-2019 Ilkka Seppälä
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
24+
package com.iluwatar.updatemethod;
25+
26+
import org.junit.After;
27+
import org.junit.Assert;
28+
import org.junit.Before;
29+
import org.junit.Test;
30+
31+
public class SkeletonTest {
32+
33+
private Skeleton skeleton;
34+
35+
@Before
36+
public void setup() {
37+
skeleton = new Skeleton(1);
38+
}
39+
40+
@After
41+
public void tearDown() {
42+
skeleton = null;
43+
}
44+
45+
@Test
46+
public void testUpdateForPatrollingLeft() {
47+
skeleton.patrollingLeft = true;
48+
skeleton.setPosition(50);
49+
skeleton.update();
50+
Assert.assertEquals(49, skeleton.getPosition());
51+
}
52+
53+
@Test
54+
public void testUpdateForPatrollingRight() {
55+
skeleton.patrollingLeft = false;
56+
skeleton.setPosition(50);
57+
skeleton.update();
58+
Assert.assertEquals(51, skeleton.getPosition());
59+
}
60+
61+
@Test
62+
public void testUpdateForReverseDirectionFromLeftToRight() {
63+
skeleton.patrollingLeft = true;
64+
skeleton.setPosition(1);
65+
skeleton.update();
66+
Assert.assertEquals(0, skeleton.getPosition());
67+
Assert.assertEquals(false, skeleton.patrollingLeft);
68+
}
69+
70+
@Test
71+
public void testUpdateForReverseDirectionFromRightToLeft() {
72+
skeleton.patrollingLeft = false;
73+
skeleton.setPosition(99);
74+
skeleton.update();
75+
Assert.assertEquals(100, skeleton.getPosition());
76+
Assert.assertEquals(true, skeleton.patrollingLeft);
77+
}
78+
}

0 commit comments

Comments
 (0)