Skip to content

Commit

Permalink
Merge branch 'main' into non-functional-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Posfay authored May 22, 2024
2 parents fb16124 + fd6fd90 commit 1afd358
Show file tree
Hide file tree
Showing 36 changed files with 606 additions and 156 deletions.
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,19 @@ sourceSets {
srcDirs = ['src']
}
}
test {
java {
srcDirs = ['test']
}
}
}

mainClassName = "macaroni.Main"

dependencies {
testImplementation 'junit:junit:4.13.1'
testImplementation 'org.junit.jupiter:junit-jupiter'
implementation 'org.junit.jupiter:junit-jupiter-api:5.5.1'
}

sonar {
Expand Down
41 changes: 41 additions & 0 deletions doc/ManualUI.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
= Manual UI

Manual UI testing is essential for modern applications. User experience and interface presentation are crucial factors when choosing applications among dozens of similar options available to users.

Running the application was the first test, during which we needed to identify UI issues such as disallowed or unclear instructions and ambiguous user interactions.

After the initial testing, we discovered 5 major issues that needed fixing.

== Data type error

Input values were added to a list without validation, with no restrictions on characters. To fix this, we updated the function that handles input parameters to only accept allowed names. The updated function restricts inputs to only include lowercase and uppercase letters (A-Z) and numbers, excluding whitespace.

image::pictures/typeError.png[width=250]

== Field widths

There were no restrictions on the length of input values (player name), allowing names of any length to be added to the player list. To fix this, we introduced an additional check to ensure that player names can be a maximum of 10 characters long.

image::pictures/unlimitedChars.png[width=250]

== Navigational elements

During application runtime, there was no option to exit because it used full-screen mode without an exit or close button. To implement an exit option, we created a CloseButton class, accessible from the main menu and during gameplay, allowing the application to be closed at any time.

image::pictures/exitInMenu.png[width=400]

image::pictures/exitGame.png[width=400]

== Error logging

The application did not properly log information or errors. To fix this, we introduced Loggers using the _java.util.logging.Logger_ class, which logs all significant events. Several classes were modified to incorporate this logging functionality.

== Menu items

In the main menu, the _Start_ button was always clickable, even when no map was selected or there weren't enough players. Instructions for the user were unclear about what needed to be completed to start the game. To improve clarity in user interaction, the _Start_ button in the main menu is now only clickable when the conditions required to start the game are met (map selected, sufficient players).

image::pictures/waiting.png[alt="Waiting for a player",width=500]

== Summary

The user interface is a critical aspect of the application. In our application, there were no security risks, and the goal was merely to enhance the user experience. Finding the issues is easy, but often it is challenging to determine how to fix them.
31 changes: 31 additions & 0 deletions doc/UnitTest.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Unit testing is inevitable in any larger projects, because with the increasing complexity of a project, it's getting close to impossible to test the whole code in one go. Unit test focus on a small, elaborate part of the code and thus, provide help with localizing issues.

This particular project was well-designed, which is proven by the fact that every unit-test have passed.

There were 4 major test classes, with the following methods:

1.) Vector2DTest
The methods in this class test the functionality of the math package, namely:
-add
-dot
-length
-scale
-normalize
-toPosition

2.) PlumberTest
The methods in this class test the functionality related to the plumber character (as such, they some of them are bound to test the methods of the Character class and other, plumber-related classes):
-repair
-pickUpPump
-placePump

3.) SaboteurTest
The methods in this class test the functionality of the saboteur character, and some related classes, for instance the content of the action package:
-dropbanana
-applyTechnokol
-getLocation
-setPipeIO

4.) SpringTest
The methods in this class test the functionality of the Spring element and some water related methods:
-tick: test the addPipe function of the Element class and whether the Spring really distributes the expected amount of water via its tick method
Binary file added doc/pictures/exitGame.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/pictures/exitInMenu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/pictures/typeError.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/pictures/unlimitedChars.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/pictures/waiting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions src/macaroni/actions/Action.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,25 @@
import macaroni.model.element.Element;
import macaroni.model.element.Pipe;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Felhasználói interakciók kezelésére használt osztály.
*/
public abstract class Action {

// Logger inicializálása
private static final Logger LOGGER = Logger.getLogger(Action.class.getName());

/**
* Minden esetben hamissal tér vissza.
*
* @param element az elem, amin action-t szeretnénk végezni.
* @return Minden esetben hamissal tér vissza.
*/
public boolean doAction(Element element) {
log("doAction(Element) metódus meghívása");
return false;
}

Expand All @@ -24,6 +31,16 @@ public boolean doAction(Element element) {
* @param pipe a cső, amin action-t szeretnénk végezni.
*/
public boolean doAction(Pipe pipe) {
log("doAction(Pipe) metódus meghívása");
return doAction((Element) pipe);
}

/**
* Logolás készítése.
*
* @param message a logolandó üzenet
*/
private void log(String message) {
LOGGER.log(Level.INFO, message);
}
}
7 changes: 5 additions & 2 deletions src/macaroni/actions/DetachPipeAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
import macaroni.model.element.ActiveElement;
import macaroni.model.element.Pipe;
import macaroni.views.PipeView;
import java.util.logging.Logger;
import java.util.logging.Level;


/**
* Cső aktív elemről való lekötési interakciót kezelő osztály.
*/
public class DetachPipeAction extends Action {

private static final Logger logger = Logger.getLogger(DetachPipeAction.class.getName());
/**
* A szerelő, aki az akciót végzi
*/
Expand Down Expand Up @@ -41,7 +44,7 @@ public DetachPipeAction(Plumber actor, ActiveElement activeElement) {
public boolean doAction(Pipe pipe) {
var success = actor.detachPipe(activeElement, pipe);
if (success) {
System.out.println("Detach pipe success");
logger.info("Detach pipe success");
var detachedPipeView = (PipeView) ViewRepository.getViewOfObject(pipe);
detachedPipeView.replaceEndpointPos(
ViewRepository.getViewOfObject(activeElement).getPosition(),
Expand Down
7 changes: 5 additions & 2 deletions src/macaroni/actions/MoveAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
import macaroni.model.element.Element;
import macaroni.views.CharacterView;
import macaroni.views.PipeView;
import java.util.logging.Logger;
import java.util.logging.Level;


/**
* Mozgási interakciót kezelő osztály.
*/
public class MoveAction extends Action {

private static final Logger logger = Logger.getLogger(MoveAction.class.getName());
/**
* A karakter, ami a mozgást végzi.
*/
Expand All @@ -36,7 +39,7 @@ public MoveAction(Character actor) {
public boolean doAction(Element element) {
var locationBeforeMove = actor.getLocation();
var success = actor.moveTo(element);
System.out.println("Move success: " + success);
logger.info("Move success: " + success);
if (success) {
var characterView = (CharacterView) ViewRepository.getViewOfObject(actor);
characterView.setPosition(ViewRepository.getViewOfObject(element).getPosition());
Expand Down
11 changes: 10 additions & 1 deletion src/macaroni/actions/SetPumpInputAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,19 @@
import macaroni.model.element.Pump;
import macaroni.views.PumpView;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Pumpa bemeneti csőállítási interakciót kezelő osztály.
*/
public class SetPumpInputAction extends Action {

/**
* Logger inicializálása
*/
private static final Logger LOGGER = Logger.getLogger(SetPumpInputAction.class.getName());

/**
* A karakter, aki az akciót végzi
*/
Expand All @@ -24,7 +32,7 @@ public class SetPumpInputAction extends Action {
* Létrehoz egy SetPumpInputAction példányt.
*
* @param actor A karakter, aki az akciót végzi
* @param pump A pumpa, amin az akciót végzi
* @param pump A pumpa, amin az akciót végzi
*/
public SetPumpInputAction(Character actor, Pump pump) {
this.actor = actor;
Expand All @@ -43,6 +51,7 @@ public boolean doAction(Pipe pipe) {
if (success) {
var pumpView = (PumpView) ViewRepository.getViewOfObject(pump);
pumpView.setInputPipePos(ViewRepository.getViewOfObject(pipe).getPosition());
LOGGER.log(Level.INFO, "Pump input pipe set successfully");
}
return success;
}
Expand Down
12 changes: 11 additions & 1 deletion src/macaroni/actions/SetPumpOutputAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,19 @@
import macaroni.model.element.Pump;
import macaroni.views.PumpView;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Pumpa kimeneti csőállítási interakciót kezelő osztály.
*/
public class SetPumpOutputAction extends Action {

/**
* Logger inicializálása
*/
private static final Logger LOGGER = Logger.getLogger(SetPumpOutputAction.class.getName());

/**
* A karakter, aki az akciót végzi
*/
Expand All @@ -24,7 +32,7 @@ public class SetPumpOutputAction extends Action {
* Létrehoz egy SetPumpOutputAction példányt.
*
* @param actor A karakter, aki az akciót végzi
* @param pump A pumpa, amin az akciót végzi
* @param pump A pumpa, amin az akciót végzi
*/
public SetPumpOutputAction(Character actor, Pump pump) {
this.actor = actor;
Expand All @@ -43,6 +51,8 @@ public boolean doAction(Pipe pipe) {
if (success) {
var pumpView = (PumpView) ViewRepository.getViewOfObject(pump);
pumpView.setOutputPipePos(ViewRepository.getViewOfObject(pipe).getPosition());
// Fontos esemény logolása
LOGGER.log(Level.INFO, "Pump output pipe set successfully");
}
return success;
}
Expand Down
25 changes: 13 additions & 12 deletions src/macaroni/app/App.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
package macaroni.app;

/**
* Represents the main application
*/
import java.util.logging.Logger;
import java.util.logging.Level;

public final class App {
/**
* shows whether the app is currently running
*/

private static final Logger logger = Logger.getLogger(App.class.getName());

boolean running = false;
/**
* the window of the application
*/

private final Window window = new Window();

/**
* Runs the application
*/
public void run() {
logger.info("Application started.");
running = true;
window.open();

Expand All @@ -29,8 +25,10 @@ public void run() {
long elapsedTime = currentLoopTime - lastLoopTime;

if (window.shouldClose()) {
logger.info("Window should close. Stopping application.");
running = false;
}

if (elapsedTime >= OPTIMAL_TIME) {
window.repaint();
lastLoopTime = currentLoopTime;
Expand All @@ -39,13 +37,16 @@ public void run() {
long sleepTime = lastLoopTime - System.currentTimeMillis() + OPTIMAL_TIME;
if (sleepTime >= 0) {
try {
logger.fine("Sleeping for " + sleepTime + " ms.");
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
logger.log(Level.SEVERE, "Thread was interrupted. Stopping application.", e);
running = false;
}
}
}

window.close();
logger.info("Application stopped.");
}
}
Loading

0 comments on commit 1afd358

Please sign in to comment.