How to write a junit test script? - java

I wrote a java code which is working but I have to write a Junit Test Script for it, but I do not have the experience yet. I tried several hours, but I can not understand how it works. So your help is very welcomed. Thanks in advance :) Do you have any tipps for me? :)
import java.awt.*;
import java.awt.event.*;
class MailBox extends Frame {
private boolean request;
private String message;
TextField tf1;
public MailBox() {
Dimension screenDim = getToolkit().getScreenSize();
Dimension frameDim = getPreferredSize();
setLocation((screenDim.width-frameDim.width)/2, (screenDim.heightframeDim.height)/2); addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
}
Panel myPanel = new Panel();
myPanel.setLayout(new FlowLayout());
Label label1 = new Label("Message: ");
Button button1 = new Button("Send");
button1.addActionListener(new button1AL());
tf1 = new TextField("", 20);
myPanel.add(label1);
myPanel.add(tf1);
myPanel.add(button1);
add(myPanel, BorderLayout.CENTER);
setTitle("Mailbox");
pack();
show();
}
public synchronized void storeMessage(String message){
while(request==true){
try{
wait();
}
catch(InterruptedException e){
}
}
request = true;
this.message = message;
notify();
}
public synchronized String retrieveMessage(){
while(request==false){
try{
wait();
}
catch(InterruptedException e){
}
}
request=false;
notify();
return message;
}
public static void main(String args[]) {
System.out.println("Starting Mailbox...");
MailBox MyMailBox = new MailBox();
Consumer c1 = new Consumer(MyMailBox);
Thread t1 = new Thread(c1);
t1.start();
}
class button1AL implements ActionListener{
public void actionPerformed(ActionEvent ae){
storeMessage(tf1.getText());
tf1.setText("");
}
}
}

I would say that in your case the program did not reach yet the level when it should be Unit tested. I don't see any reason why you need to test that some constructor works when it just initializes the fields of the class and also that the program prints something. I would not check that.
In the case when you get some error and this error might contain different error messages, it is a good idea to verify that the message is the same, but this is not your case. So, the main point is that your unit test should test business logic.
Consider this template:
#Test
public void testGoUntilTankIsEmpty() throws Exception {
// SETUP SUT
Car car = new Car();
car.fillFullTank();
car.setSpeed(80);
// EXERCISE
int distanceInKm = car.goUntilTankIsEmpty();
// VERIFY
Assert.assertEquals(800, distanceInKm);
}
In this case we exercise (test) specified method and expect that the result will be 800 based on our preliminary setup. If it is true your unit test will pass otherwise it will fail.
And remember that unit test should test only some unit, so some small piece of code, but actual functionality.

JUnit's work by testing the code you have written with either the expected output, or incorrect output if you want to test whether your error handling works.
In your case you'd just test against the expected string it outputs.
So a basic test for what you have would look something along the lines of...
import org.junit.Test;
import org.junit.Assert.assertEquals
public class BasicTest{
#Test
public void describeAnimalTest(){
AnimalNew animal = new AnimalNew("Dog", 10, "x");
assertEquals("Dog is on level 10 und is a type of x", animal.describeAnimal();
}
}

Related

Awaiting for message using discordJDA not working as intended

I'm currently working on my discord bot. One problem I encountered is that I'm not able to find out how to allow the bot to wait for a user reply after a message is sent.
I also have tried reading the git documentation regarding using RestAction over here: https://github.com/DV8FromTheWorld/JDA/wiki/7)-Using-RestAction but it seems it does not mention anything about implementing an "await" function similar to discord.js
I tried coding to mimic such an effect:
public class EventHandler extends ListenerAdapter {
private static final String PREFIX = "&";
public static String[] args;
public void sendMessage(String s, GuildMessageReceivedEvent event) {
event
.getChannel()
.sendMessage(s)
.queue();
}
public void onGuildMessageReceived (GuildMessageReceivedEvent event) {
args = event
.getMessage()
.getContentRaw()
.split(" ");
if (args[0].equalsIgnoreCase(PREFIX + "any_command")) {
sendMessage("Type hello!");
if (args[0].equalsIgnoreCase(PREFIX + "hello") {
sendMessage("hello there!");
}
}
}
}
Main class:
import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder;
public class Main {
public static void main(String[] args) throws Exception {
JDA jda = new JDABuilder(AccountType.BOT)
.setToken("token goes here")
.setAutoReconnect(true).build();
try {
jda.addEventListener(new EventHandler());
} catch (Exception e) {
e.printStackTrace();
}
}
}
This doesn't register the hello command typed after the prompt given. My best guess would be that the condition is never met since the original condition overrides the upcoming one (args[0] is already any_command)
Any help would be appreciated!
I'd suggest the EventWaiter from JDA-Utilities (https://github.com/JDA-Applications/JDA-Utilities/)
Taking a quick look at the source, looks like you'll need something like this
EventWaiter waiter = new EventWaiter();
// SO wouldn't let me insert new lines for some reason.
waiter.waitForEvent(GuildMessageReceivedEvent.class, (event) -> event.getMessage().getContentRaw().equalsIgnoreCase("hello"), (event) -> event.getChannel().sendMessage("hello!").queue()));

simulate key press in JUnit tests

I am completely stuck in a java test; it's about sending by the test method the character 'a' to the JTextField of a JFrame component.
The JFrame class implements the KeyListener interface, and as such overrides KeyPressed, KeyTyped, and KeyReleased. Along with this, I transfer all the keypressed of the JTextField to the JFrame; inside the JFrame constructor I have :
JTextField txf_version = new JTextField();
txf_version.addKeyListener(this);
I would like to test this behavior and then to simulate the action of type a character in the JTextField.
all my attempts failed; I tried with the java.awt.Robot class, like this : hava a look at this other post in stack overflow, but I get a strange behavior : calling
robot.keyPress(KeyEvent.VK_A);
displays the character in my IDE directly, not in the virtual JFrame! try to play with requestFocus() or requestFocusInWindow() is ineffective.
I also tried with KeyEvents:
KeyEvent key = new KeyEvent(bookWindow.txf_version, KeyEvent.KEY_PRESSED, System
.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, 'a');
bookWindow.txf_version.dispatchEvent(key);
but again the textfield's text property is not changed...
here is the method I have for now:
#Test
void testBtnSaveChangesBecomesRedWhenVersionChanged() throws AWTException,
InterruptedException, NoSuchFieldException, IllegalAccessException {
initTest();
KeyEvent key = new KeyEvent(bookWindow.txf_version, KeyEvent.KEY_PRESSED, System
.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, 'a');
bookWindow.txf_version.dispatchEvent(key);
System.out.println("dans txf_version : " + bookWindow.txf_version.getText
());
assertEquals(Color.RED, bookWindow.getBtnSaveChangesForegroundColor());
}
I can have a look at the actual behavior by writing a main() method in the JFrame's child class, but I think it is useful to know how to simulate keys for swing components testing.
thank you
EDIT:
I changed the code of my test according to AJNeufeld's answer, but it still doesn't work. Here is my test code :
#Test
void testBtnSaveChangesBecomesRedWhenVersionChanged() throws AWTException,
InterruptedException, NoSuchFieldException, IllegalAccessException,
InvocationTargetException {
//bookEditor2 & bookWindow
SwingUtilities.invokeAndWait(() -> {
bookWindow = new BookWindow();
VectorPerso two = new VectorPerso();
two.add(le_livre_de_la_jungle);
two.add(elogeMaths);
bookWindow.setTableDatas(two);
bookWindow.table.setRowSelectionInterval(1, 1);
bookWindow.txf_version.requestFocusInWindow();
KeyEvent key = new KeyEvent(bookWindow.txf_version, KeyEvent.KEY_TYPED, System
.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, 'a');
bookWindow.txf_version.dispatchEvent(key);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("dans txf_version : " + bookWindow.txf_version.getText
());
assertEquals(Color.RED, bookWindow.getBtnSaveChangesForegroundColor());
});
}
the plintln line produces a text in the console : "dans txf_version : 0", which indicates the key isn't send to the txf_version.
EDIT 2:
new try:
#Test
void testBtnSaveChangesBecomesRedWhenVersionChanged() throws AWTException,
InterruptedException, NoSuchFieldException, IllegalAccessException,
InvocationTargetException {
//bookEditor2 & bookWindow
SwingUtilities.invokeAndWait(() -> {
bookWindow = new BookWindow();
VectorPerso two = new VectorPerso();
two.add(le_livre_de_la_jungle);
two.add(elogeMaths);
bookWindow.setTableDatas(two);
bookWindow.table.setRowSelectionInterval(1, 1);
bookWindow.txf_version.requestFocusInWindow();
KeyEvent key = new KeyEvent(bookWindow.txf_version, KeyEvent.KEY_TYPED, System
.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, 'a');
bookWindow.txf_version.dispatchEvent(key);
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SwingUtilities.invokeAndWait(() -> {
System.out.println("dans txf_version : " + bookWindow.txf_version.getText
());
assertEquals(Color.RED, bookWindow.getBtnSaveChangesForegroundColor());
});
}
I think you're doing a couple of things wrong, but without a complete example, it is hard to tell.
First, the JTextField is not really concerned with KEY_PRESSED events. It is concerned with the KEY_TYPED events.
Second, Swing processes events on the Event Dispatching Thread (EDT), which is not necessarily the thread that JUnit is going to be running on. You really shouldn't be changing things when you're not on the EDT. I'm not certain eventDispatch() does the switch to the EDT or not. It might. But it might also do it using invokeLater(), in which case the execution immediately passes to the assertEquals(), which fails, because the event processing hasn't happened yet.
Here is minimal, complete, verifiable example, which shows a keypress sent, which changes the button colour, and a JUnit test case which checks it and passes:
First, the code under test:
public class SwingUnitTesting extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(SwingUnitTesting::new);
}
JTextField tf = new JTextField();
JButton btn = new JButton("Test Button");
SwingUnitTesting() {
add(tf, BorderLayout.PAGE_END);
add(btn, BorderLayout.PAGE_START);
tf.addKeyListener(new KeyAdapter() {
#Override
public void keyTyped(KeyEvent e) {
btn.setForeground(Color.RED);
}
});
setSize(200, 80);
setLocationByPlatform(true);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setVisible(true);
}
}
And the unit test:
public class SwingUnitTestingTest {
SwingUnitTesting sut;
#Before
public void setUp() throws Exception {
SwingUtilities.invokeAndWait(() -> {
sut = new SwingUnitTesting();
});
}
#Test
public void btnNotRedBeforeKeypress() throws InvocationTargetException, InterruptedException {
SwingUtilities.invokeAndWait(() -> {
assertNotEquals(Color.RED, sut.btn.getForeground());
});
}
#Test
public void btnRedAfterKeypress() throws InvocationTargetException, InterruptedException {
SwingUtilities.invokeAndWait(() -> {
sut.tf.requestFocusInWindow();
sut.tf.dispatchEvent(new KeyEvent(sut.tf,
KeyEvent.KEY_TYPED, System.currentTimeMillis(), 0,
KeyEvent.VK_UNDEFINED, 'A'));
assertEquals(Color.RED, sut.btn.getForeground());
});
}
}
You can probably use some JUnit #Rule trickery or a custom runner to automatically change to the EDT when running swing tests.
Update:
I got curious, and tried to find an existing #Rule which puts the #Before, #Test, and #After code on to the EDT, but my Google-fu failed me;
I know I've seen it before, but I couldn't find it.
In the end, I created my own:
public class EDTRule implements TestRule {
#Override
public Statement apply(Statement stmt, Description dscr) {
return new Statement() {
private Throwable ex;
#Override
public void evaluate() throws Throwable {
SwingUtilities.invokeAndWait(() -> {
try {
stmt.evaluate();
} catch (Throwable t) {
ex = t;
}
});
if (ex != null) {
throw ex;
}
}
};
}
}
Using this rule, the JUnit test becomes a little simpler:
public class SwingUnitTestingTest {
#Rule
public TestRule edt = new EDTRule();
SwingUnitTesting sut;
#Before
public void setUp() throws Exception {
sut = new SwingUnitTesting();
}
#Test
public void btnNotRedBeforeKeypress() {
assertNotEquals(Color.RED, sut.btn.getForeground());
}
#Test
public void btnRedAfterKeypress() {
sut.tf.requestFocusInWindow();
sut.tf.dispatchEvent(
new KeyEvent(sut.tf, KeyEvent.KEY_TYPED, System.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, 'A'));
assertEquals(Color.RED, sut.btn.getForeground());
}
}
Tested on MacOS, with jdk1.8.0_121
Yo, I guess you have two choices
1) It's still to find a solution using SWING (but in this case, I have no experience and any idead how to help you).
2) It's to use Sikulli java framework for testing desktop app. You can add the dependency then
make screenshot of your UI elements, and put them into test data folder of your app
Using sikuli + JUnit
write simple test where you set a path for your pic of button (for example)
and write action, move, click or what actually you need.
in very simple that will be looks like
Button button = new Button("test-folder/pic1.jpg");
button.click();
After run, you will see that, your cursor was move on button, and click by it.
For more details, find examples in web about Sikulli + Java.
recently I had to test a customized KeyAdapter and I created a customized JTextField to dispatch key events. A piece of the code I used is bellow:
public class ProcessKeyOnTextFieldTest {
#Test
public void pressKeyTest() throws Exception {
JTextFieldWithTypedKeySupport textField = new JTextFieldWithTypedKeySupport();
textField.pressKey('a');
textField.pressKey('b');
assertEquals("ab", textField.getText());
}
class JTextFieldWithTypedKeySupport extends JTextField {
int timestamp;
void pressKey(char key) throws InvocationTargetException, InterruptedException {
SwingUtilities.invokeAndWait(() -> super.processKeyEvent(createEvent(key)));
}
KeyEvent createEvent(char keyChar) {
return new KeyEvent(this, KeyEvent.KEY_TYPED, timestamp++, 0, KeyEvent.VK_UNDEFINED, keyChar);
}
}
}

addActionListener cannot be added to given type?

code:
import java.awt.*;
import javax.swing.*;
import java.rmi.*;
import java.awt.event.*;
public class ServiceBrowser{
JPanel mainPanel;
JComboBox serviceList;
ServiceServer server;
public void buildGUI(){
JFrame frame = new JFrame("RMI Browser");
mainPanel = new JPanel();
frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
Object[] services = getServiceList();
//rmi registry lookup, get stub, call getServiceList
serviceList = new JComboBox(services);
//add services(array of objects) to Jcombobox,
//knows how to make displayable strings out of
//each thing in array
frame.getContentPane().add(BorderLayout.NORTH, serviceList);
serviceList.addActionListener(new MyListListener());
frame.setSize(500,500);
frame.setVisible(true);
}//end buildGUI
void loadService(Object serviceSelection){
try{
Service svc = server.getService(serviceSelection);
mainPanel.removeAll();
mainPanel.add(svc.getGuiPanel());
mainPanel.validate();
mainPanel.repaint();
} catch(Exception ex){
ex.printStackTrace();
}//add actual service to gui after user selects one
//(this method called by event listener on combobox)
//call getService() on remote server(stub), pass it
//same string in the list, server returns actual service(serialized)
//and call getGuiPanel on service and add result (jpanel) to browser mainpanel
}
Object[] getServiceList(){
Object obj = null;
Object[] services = null;
try{
obj = Naming.lookup("rmi://127.0.0.1/ServiceServer");
} catch(Exception ex){
ex.printStackTrace();
}
server = (ServiceServer) obj;
//cast the stub to remote interface so we can call getServiceList on it
try{
services = server.getServiceList();
}catch(Exception ex){ex.printStackTrace();}
}
class MyListListener implements ActionListneer{
public void actionPerformed(ActionEvent ev){
Object selection = serviceList.getSelectedItem();
loadService(selection);
//user made selection from jcombobox list, take selection
//load appropriate service
}
}
public static void main(String[] args){
new ServiceBrowser().buildGUI();
}
}
error:
row 25: addactionlistener in class JComboBox<e> cannot be applied to given type
serviceList.addActionListener(new MyListListener());
ServiceBrowser.java uses unchecked or unsafe operations
I know this means that there is a collection somewhere that doesn't declare its type, but I am not sure what is the issue. I think it has something to do with serviceList taking an array of objects? JComboBox constructor says it takes a list of objects, so I am not sure the error.
Small typo:
class MyListListener implements ActionListeneer {
^
should be
class MyListListener implements ActionListener {

Maximum coverage of JUnit Test case

Tests should have good coverage of the types of exceptions and errors that this class can throw, and it should have good coverage of the defective statements in the constructor method for CalculatePrimesMother.
The method for which three Junit test case needed is as below:
public CalculatePrimesMother(int numWorkers, int queueLength, int maxPrime,
boolean verbose) {
this.numWorkers = numWorkers;
// Instantiate 3 queues, for thread-safe communication with workers
Candidate = new ArrayBlockingQueue<Integer>(queueLength);
Prime = new ArrayBlockingQueue<Integer>(queueLength);
Composite = new ArrayBlockingQueue<Integer>(queueLength);
this.maxPrime = maxPrime;
this.sqrtMaxPrime = (int) Math.sqrt(maxPrime);
primeFactors = new int[sqrtMaxPrime];
this.verbose = verbose;
}
I tried and created some test case but not able to get full coverage can anyone help me?
public class CalculatePrimesMotherTest extends TestCase {
public CalculatePrimesMotherTest(String name) {
super(name);
}
private CalculatePrimesMother testMother;
#Test
public final void testCalculatePrimesMotherNegativequeueLength() {
try {
testMother = new CalculatePrimesMother(4, -12, 908, false);
} catch (Exception e) {
e.printStackTrace();
}
}
#Test
public final void testCalculatePrimesMotherMinusOne() {
try {
testMother = new CalculatePrimesMother(8, 12, 0, true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
What coverage do you get? There are no if tests in your ctor, so a single call should exercise all the code that I see.
You're writing too much code. The setUp and tearDown and test constructor methods are all unnecessary. Remove them.
You don't need the try/catch blocks in the other tests. Remove those, too. You want an exception to trigger a test failure. Catching will hide the error.

How is GUI code being invoked before my Scanner?

I'm having some trouble with getting input from the command line before opening a GUI window. I asked this question previously on Apple Exchange but was sent here after we determined it to be a Programming problem. Basically I'm running a Scanner to get user input before I open up a window but it starts the program, switching spaces on my Mac, and then I have to switch back to the workspace with the terminal in it to answer the question. Here's a link to the original question.
https://apple.stackexchange.com/questions/45058/lion-fullscreen-desktop-switching-quirk/45065#comment51527_45065
Here's the code I've tested with...
public class Client extends JFrame {
public static void main(String[]args) {
Scanner in = new Scanner(System.in);
System.out.printf("\nGive me a size for the screen: ");
String response = in.nextLine();
new Client(response);
}
public Client(String title) {
super(title);
super.setVisible(true);
}
}
Use invokeLater() to start the GUI after you get the input.
final String response = in.nextLine();
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Client(response);
}
});
Note that your example runs fine on my platform due to timing differences. Also consider using the args array to pass parameters, or ask the implementation, as shown in FullScreenTest
Addendum: Reading your other thread a little closer, you can use the following approach that launches a NamedFrame in a separate JVM.
package cli;
import java.awt.EventQueue;
import java.io.IOException;
import java.util.Scanner;
import javax.swing.JFrame;
/** #see https://stackoverflow.com/q/9832252/230513 */
public class CommandLineClient {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Give me a name for the screen: ");
final String response = in.nextLine();
try {
ProcessBuilder pb = new ProcessBuilder(
"java", "-cp", "build/classes", "cli.NamedFrame", response);
Process proc = pb.start();
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
}
}
class NamedFrame extends JFrame {
public NamedFrame(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationByPlatform(true);
setVisible(true);
}
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new NamedFrame(args[0]);
}
});
}
}
Code appears to be ok. Is there any class level stuff in Client that you haven't shown here (e.g. static members etc?)
The whole switching workspaces description in your link is an OS level thing NOT java specifically.
Is there options to the java command or something on mac you could use?

Categories

Resources