Melakukan Pengujian Java Swing Dengan FEST


Pada aplikasi web, saya dapat melakukan pengujian view HTML dengan menggunakan Selenium.  Bagaimana dengan aplikasi desktop? Apakah saya juga bisa melakukan pengujian user interface?  Yup, bisa!  Salah satu tool yang dapat saya pergunakan adalah FEST (Fixtures for Easy Software Testing).

Untuk memakai FEST, saya perlu men-download fest-swing-1.2.zip dari http://code.google.com/p/fest. Di dalam file tersebut, saya akan menemukan file fest-swing-1.2.jar yang harus disertakan dalam proyek yang akan diuji. Selain itu, saya juga perlu menyertakan jar yang ada di dalam folder lib seperti fest-util-1.1.2.jar dan fest-assert-1.2.jar.  Btw, di saat sedang serius, saya lebih memilih memakai Maven untuk melakukan proses download secara otomatis dengan menyertakan dependency ke org.easytesting.fest-swing.

Saya akan membuat sebuah tampilan Swing yang akan diuji dengan menggunakan MigLayout seperti berikut ini:

package com.snake.view;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import net.miginfocom.swing.MigLayout;

public class LoginView extends JFrame {

	private static final long serialVersionUID = -1977819063823609321L;

	private JTextField txtNama;
	private JPasswordField txtPassword;
	private JButton btnLogin;
	private JButton btnKeluar;

	public LoginView() {
		super("Login");

		setLayout(new MigLayout("", "[right][grow,fill]", "[][][nogrid]"));
		add(new JLabel("Nama Pengguna:"));
		add(txtNama = new JTextField(20), "wrap");		
		add(new JLabel("Password:"));
		add(txtPassword = new JPasswordField(20), "wrap");
		add(btnLogin = new JButton("Login"), "align center, gaptop 10");
		add(btnKeluar = new JButton("Keluar"));

		txtNama.setName("txtNama");
		txtPassword.setName("txtPassword");
		btnLogin.setName("btnLogin");
		btnKeluar.setName("btnKeluar");

		btnLogin.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (txtNama.getText().equals("solid") &&
						String.valueOf(txtPassword.getPassword()).equals("snake")) {
					JOptionPane.showMessageDialog(LoginView.this, "Ok, login sukses!");
				} else {
					JOptionPane.showMessageDialog(LoginView.this, "Maaf, kamu bukan dia!");
				}
			}

		});

		setSize(500,500);
		pack();		
	}

	public static void main(String[] args) {
		LoginView loginView = new LoginView();
		loginView.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		loginView.setVisible(true);
	}

}

Lalu, untuk melakukan pengujian, saya membuat sebuah JUnit test seperti berikut ini:

package com.snake.view;

import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.fixture.FrameFixture;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class LoginViewTest {

	private FrameFixture window;

	@BeforeClass
	public static void beforeClass() {
		FailOnThreadViolationRepaintManager.install();
	}

	@Before
	public void before() {

		LoginView loginView = GuiActionRunner.execute(new GuiQuery<LoginView>() {
			@Override
			protected LoginView executeInEDT() throws Throwable {
				return new LoginView();
			}
		});
		window = new FrameFixture(loginView);
		window.show();
	}

	@After
	public void after() {
		window.cleanUp();
	}

	@Test
	public void testTampilanAwal() {
		window.textBox("txtNama").requireEditable().requireEmpty();
		window.textBox("txtPassword").requireEditable().requireEmpty();
		window.button("btnLogin").requireVisible();
		window.button("btnKeluar").requireVisible();
	}

	@Test
	public void testLoginSukses() {
		window.textBox("txtNama").enterText("solid");
		window.textBox("txtPassword").enterText("snake");
		window.button("btnLogin").click();
		// Menunggu JOptionPane muncul dengan timeout default 100ms
		window.optionPane().requireMessage("Ok, login sukses!");
	}

	@Test
	public void testLoginGagal() {
		window.textBox("txtNama").enterText("user aneh");
		window.textBox("txtPassword").enterText("password ajaib");
		window.button("btnLogin").click();
		// Menunggu JOptionPane muncul dengan timeout default 100ms
		window.optionPane().requireMessage("Maaf, kamu bukan dia!");
	}
}

Pada pengujian di atas, saya memberikan statement FailOnThreadViolationRepaintManager.install() untuk mendeteksi apakah ada kode program yang mengakses Swing tetapi tidak berjalan di EDT. Saya membahas tentang EDT di tulisan Multithreading Dengan Mudah Di Griffon.   Pada tulisan tersebut saya memakai bahasa Griffon, sementara disini saya memakai bahasa Java.  Tapi keduanya sama-sama berjalan di platform Java sehingga prinsip dasar-nya tetap sama.    Bila terdapat pelanggaran saat JUnit dijalankan, pada console akan terdapat output seperti org.fest.swing.exception.EdtViolationException: EDT violation detected.

Ini adalah contoh hasil yang saya peroleh saat menjalankan JUnit test case di atas:

Hasil Pengujian

Hasil Pengujian

Pada saat memakai JUnit dengan Selenium, browser akan muncul dan men-klik “sana-sini” secara otomatis.  Begitu juga dengan sekarang.  Saat memakai FEST, JFrame yang diuji akan muncul, setiap JTextField akan di-isi, kemudian JButton akan di-click.

Perihal Solid Snake
I'm nothing...

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: