Oop lab/unit testing slick2d
- หน้านี้เป็นส่วนหนึ่งของ oop lab.
เราต้องการจะเขียน unit test กับโค้ดใน Slick2D อย่างไรก็ตามโค้ดส่วนของ Entity ของเรานั้นมักมีส่วนการแสดงผลอยู่ด้วย และส่วนเหล่านี้โดยมากจะทำงานไม่ได้ใน unit test หรือไม่ก็ทำให้การเตรียมการต่าง ๆ มีปัญหา
เพื่อเพิ่มความเข้าใจ เราจะยกตัวอย่างจากโค้ด BulletGame แต่เราจะเพิ่มให้คลาส Bullet ใช้รูปลูกกระสุน แทนที่จะเป็นการวาดรูปธรรมดา
ในการทำ unit test นั้น เราจะทดลองเพิ่มเมท็อด distanceTo(float x, float y) ให้กับคลาส Bullet เป็นตัวอย่าง
เนื้อหา
Bullet ที่แสดงโดยการวาดรูป
เพื่อเป็นการทดลอง เราจะใช้รูป ship จาก ship เกมในการแสดงกระสุน เมื่อรันแล้วอาจจะมีหน้าตาแบบนี้
เราจะคัดลอกไฟล์ ship.png มาใส่ในไดเร็กทอรี res และเพิ่ม field image, แก้ constructor, และปรับเมท็อด render ในคลาส Bullet ดังนี้
public class Bullet implements Entity {
//...
protected Image image;
public Bullet(float x, float y) {
try {
image = new Image("res/ship.png"); // this line is problematic.
} catch (SlickException e) {
e.printStackTrace();
}
this.setXY(x,y);
}
public void render(Graphics g) {
image.draw(getX(), getY());
//g.fillOval(getX(), getY(), BULLET_SIZE, BULLET_SIZE); --- this is removed line
}
//...
}
หมายเหตุ: block try-catch นั้นอาจจะดูรกรุงรัง แต่จำเป็นเพราะว่าการเปิด image ใหม่นั้น อาจจะเกิด exception ขึ้นได้
ทดลอง unit test
ในโค้ด unit test ของเรา เราจะทดลองแค่สร้าง bullet มาก่อน
public class BulletTest {
@Test
public void testBulletCanBeCreated() {
Bullet b = new Bullet(10,20);
}
}
เมื่อเราเรียกให้ unit test ทำงาน เราจะพบ error ดังนี้
java.lang.RuntimeException: No OpenGL context found in the current thread. at org.lwjgl.opengl.GLContext.getCapabilities(GLContext.java:124) at org.lwjgl.opengl.GL11.glGetError(GL11.java:1289) at org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer.glGetError(ImmediateModeOGLRenderer.java:384) at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:249) at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:187) ... at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
เพราะว่าจะเปิด Image ได้นั้น โปรแกรมของเราจะต้องมีการจัดการเปิดหน้าต่างและจัดการเกี่ยวกับ OpenGL ก่อน ซึ่งในส่วนนี้ เรามักจะไม่ดำเนินการใน Unit test
การเขียนโปรแกรมให้ test ได้ง่ายนั้น เป็นทักษะแบบหนึ่งที่มีประโยชน์มาก และโดยมาก ความพยายามที่จะทำให้โปรแกรม test ได้ง่าย จะทำให้เราได้รับโค้ดที่ดีมีคุณภาพด้วย
วิธีที่ 1: สร้าง Image ยามต้องการ
เพื่อให้โค้ด test ได้ โค้ดทุกส่วนที่เกี่ยวข้องกับการทำงานทั่วไป (ที่ไม่เกี่ยวกับการแสดงผล) จะต้องไม่มีการจัดการเกี่ยวกับการแสดงผลเลย และจะมีโค้ดเกี่ยวกับการแสดงผลเมื่อจำเป็น เช่นเมื่อมีการเรียก render แล้ว
เราจะแก้ constructor ของเราดังนี้
public Bullet(float x, float y) {
image = null;
this.setXY(x,y);
}