Skip to content

Commit

Permalink
Merge pull request #11 from BME-MIT-IET/Nem-funkcionális-részek-teszt…
Browse files Browse the repository at this point in the history
…elése

Nem funkcionális részek tesztelése
  • Loading branch information
voroscsoki authored May 21, 2024
2 parents 9a4c594 + c7c48bd commit 9462c97
Show file tree
Hide file tree
Showing 15 changed files with 233 additions and 11 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import javax.swing.WindowConstants;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JTextField;
Expand All @@ -14,7 +16,7 @@


public class Menu extends JFrame implements ActionListener {
private String currentTheme;
public String currentTheme;
private JButton newGame;
private JButton exitGame;
private JButton theme;
Expand All @@ -23,6 +25,8 @@ public class Menu extends JFrame implements ActionListener {
private JTextField mechanic;
private JTextField saboteur;

public static ViewGame vg;

/**
* konstruktor
* @param name az ablak neve
Expand Down Expand Up @@ -113,6 +117,27 @@ public void changeTheme(String s) {
}
}

public JButton getThemeButton() {
return theme;
}

public JButton getPlayButton() {
return newGame;
}

public ArrayList<JButton> getActionButtons() {
ArrayList<JButton> actionButtons = new ArrayList<JButton>();
if (vg == null) return actionButtons;

actionButtons.add(vg.repairButton);
actionButtons.add(vg.breakButton);
actionButtons.add(vg.makeSlipperyButton);
actionButtons.add(vg.makeStickyButton);
actionButtons.add(vg.putDownButton);

return actionButtons;
}

@Override
public void actionPerformed(ActionEvent e) {

Expand All @@ -139,7 +164,7 @@ public void actionPerformed(ActionEvent e) {
Controller.create();
Controller.setActivePlayer(Controller.getAllPlayers().get(0));
this.dispose();
ViewGame vg = new ViewGame();
vg = new ViewGame();
vg.setBackgroundColor(currentTheme);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ public class ViewGame extends JFrame implements ActionListener {
/**
* Controll buttons
*/
JButton moveButton;
JButton repairButton;
JButton breakButton;
JButton makeSlipperyButton;
JButton makeStickyButton;
JButton pickUpButton;
JButton putDownButton;
JButton setPumpButton;
static JButton moveButton;
static JButton repairButton;
static JButton breakButton;
static JButton makeSlipperyButton;
static JButton makeStickyButton;
static JButton pickUpButton;
static JButton putDownButton;
static JButton setPumpButton;

/**
* Last action
Expand Down Expand Up @@ -121,13 +121,27 @@ public void actionPerformed(ActionEvent e) {
}
};

public static Menu menu;

/**
* Main method
* @param args
*/
public static void main(String[] args){
Menu menu = new Menu("Menu", "White");
// measure startup time
long startTime = System.currentTimeMillis();

menu = new Menu("Menu", "White");
menu.showMenu();

// measure startup time
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
System.out.println("Startup time: " + duration + "ms");
}

public static Menu getMenuInstance() {
return menu;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import Controll.Menu;
import Controll.ViewGame;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import static java.lang.Thread.sleep;

public class ResponseTimeSampler extends AbstractJavaSamplerClient {
@Override
public Arguments getDefaultParameters() {
Arguments params = new Arguments();
params.addArgument("button", "theme"); // Default to testing the theme button
return params;
}

@Override
public SampleResult runTest(JavaSamplerContext context) {
String button = context.getParameter("button");
SampleResult result = new SampleResult();

try {
// Indítsa el a ViewGame alkalmazást
String[] args = {};
ViewGame.main(args);
Menu menu = ViewGame.getMenuInstance();
menu.showMenu();


if ("theme".equals(button)) {
result.sampleStart(); // start timing
// Téma gomb megnyomása
JButton themeButton = menu.getThemeButton();
simulateButtonClick(themeButton);
} else if ("play".equals(button)) {
result.sampleStart(); // start timing
// Play gomb megnyomása
JButton playButton = menu.getPlayButton();
simulateButtonClick(playButton);
} else if ("action".equals(button)) {
// Action gombok végignyomása
JButton playButton = menu.getPlayButton();
simulateButtonClick(playButton);
result.sampleStart(); // start timing
ArrayList<JButton> actionButtons = menu.getActionButtons();
for (JButton bt : actionButtons) {
simulateButtonClick(bt);
}
} else if ("stresstest".equals(button)) {
// Action gombok végignyomása
JButton playButton = menu.getPlayButton();
simulateButtonClick(playButton);
result.sampleStart(); // start timing
ArrayList<JButton> actionButtons = menu.getActionButtons();
for (int i = 0; i < 1000000; i++){
if (i % 100 == 0)
System.out.println(i);

for (int j = 0; j < 4; j++) {
simulateButtonClick(actionButtons.get(j));
sleep(1);
}
}
}

result.sampleEnd(); // end timing
result.setSuccessful(true);
result.setResponseMessage("Button " + button + " clicked successfully.");
result.setResponseCodeOK(); // 200 status code
} catch (Exception e) {
result.sampleEnd(); // end timing
result.setSuccessful(false);
result.setResponseMessage("Exception: " + e.toString());
}

return result;
}

private void simulateButtonClick(JButton button) {
ActionEvent event = new ActionEvent(button, ActionEvent.ACTION_PERFORMED, button.getActionCommand());
for (ActionListener listener : button.getActionListeners()) {
listener.actionPerformed(event);
}
}
}
Binary file added doc/actionbuttons.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/active.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/darkmode.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/defaultmap.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/idle.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/largemap.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/loadtimes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 92 additions & 0 deletions doc/nem-funkcionalis-tesztek.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Nem funkcionális elemek tesztelése
A tesztelés során a vízvezeték-játék nem-funkcionális jellemzőit vizsgáltam. Ez a teljesítmény, stresszbírás, biztonság és használhatóság vizsgálatát foglalja magában. A tesztelés megvalósítása során a legnagyobb nehézséget talán annak a kitalálása okozta, hogy hogyan implementáljam a tesztelő osztályt úgy, hogy a lehető legminimálisabban zavarja meg a létező kódot. A végső megoldás az lett, hogy pár változót statikussá kellett tenni, hogy a külön tesztosztályból elérhetők legyenek.

## Teljesítmény
### Indítási idő mérése
Ezt külső alkalmazás használata nélkül mértem le, tisztán a kódból, az egyszerűbb megvalósítás érdekében. 20 mérést végeztem, amiknek az eredménye az lett, hogy az indítási idő jellemzően 43 ± 1ms (99%-os konfidenciaintervallummal számolva).

![img](startup.png)

### Válaszidők mérése
Itt azt mértük, hogy a játék milyen gyorsan reagál adott felhasználói inputokra. Itt három olyan inputot találtam, amit úgy gondoltam, érdemes mérni: a megjelenítés témáját változtató gomb, a játékot elindító gomb, illetve a játék menete során nyomható "akciógombok". Ezeket a méréseket már a JMeter segítségével végeztem, a képeken annak a kimenetei láthatók.

#### Dark Mode gomb

Itt a válaszidő érthető módon azonnali volt - hiszen nem futtat a gomb semmi logikát, számítást, csak módosítja GUI elemek színét. Így tehát a mérések közül egyik sem érte el az 1ms-ot.

![img](darkmode.png)

#### Játék Indítása gomb

A mért válaszidők közül messze ez volt a legjelentősebb - ismét érthető módon, hiszen itt történik a pálya beolvasása, létrehozása, a játékosok inicializálása, és az új GUI ablak létrehozása is.

Az így kapott jellemző játékindítási idő tehát nagyjából 116 ± 6ms (szintén a 99%-os konfidenciaintervallummal számolva, a mért átlag és szórás alapján).

![img](playgame.png)

#### Akciógombok

Itt ahelyett, hogy a gombokat egyesével mérném, egyszerre 5 gomb egymás utáni megnyomására mértem a válaszidőt, aminek az adatai a mellékelt képen láthatók. Ezt átszámoltam egy egyéni gombnyomásra vonatkozó értékre, ami szerint a jellemző válaszidő egy gombnyomásra 1 ± 0.36ms (ismét 99%-os konfidenciaintervallummal számolva).

![img](actionbuttons.png)

## Stresszteszt
### Erőforrás-használat mérése

Ezekhez a mérésekhez a VisualVM szoftvert használtam, ami kifejezetten a Java alapú alkalmazások erőforráshasználatának mérésére készült. Ezen felül ezek a tesztek szintén a JMeter-ből lettek indítva, mert a terhelés során szimulált inputok azon keresztül lettek lekódolva.

#### Készenléti állapotban

Vagyis amikor a játék a játékos inputjaira vár, és ezen felül más nem történik. Mint ahogy az várható volt, a CPU terhelés ilyenkor nulla, vagy majdnem nulla. A felhasznált memória stabilan 323 MB környékén van

![img](idle.png)

#### Stresszteszt során

Ugyan az eredmény itt jelentősen más, mint az előbb, érdemes kihangsúlyozni, hogy egy lehetetlenül intenzív inputáradatot kellett szimulálni ahhoz, hogy a program erőforráshasználata jelentőssé váljon. Tehát a valóságban, rendes használat során az ehhez hasonló terhelés létrejötte lehetetlen. A terheléshez folyamatos gombnyomásokat szimuláltam, 1ms-os várakozásokkal a nyomások között. A CPU használat így (egy kezdeti ugrás után) 5% körül stabilizálódott, a memóriahasználat pedig 50 MB és 625 MB között mozgott.

![img](active.png)

### Skálázhatóság

A skálázhatóságot egyetlen módon tudtam mérni, ez pedig a pályák mérete. A többi aspektusa a játéknak nem skálázható (több játékos esetében is egyszerre mindig csak egyvalaki léphet). Öt esetet mértem, az alapértelmezett pálya méretével kezdve, és kettesével növelve a pálya méretének szorzóját (tehát az 1-9x méreteket, kettesével). Az 5x méretű pálya betöltési ideje például ez:

![img](largemap.png)

Az összes képet egyesével nem fogom beszúrni, hanem egy grafikonban összeszedve mutatom meg a skálázódást:

![img](loadtimes.png)

Az adatokból elég tisztán látszik, hogy egy lineáris összefüggésről beszélünk a bemeneti pályaméret és a betöltési idő között.

## Biztonság

### Input validáció

A tesztelés további része manuálisan történt, nem dedikált programokkal. A programban három típusú input lehetséges. Ezek a legördülő menük, a gombok, és a kattintható térkép.

A legördülő menüben és a kattintható térképen biztonságra veszélyes, vagy csalásra használható inputot nem találtam.

#### Nyomható gombok

Egyedül egy bizonsági problémát találtam az inputokkal kapcsolatban. Játék közben, amennyiben szabotőr van soron, és egy csővezetéken tartózkodik, a "Put Down Pipe" akció egy futásidejű hibát okoz.

![img](pipeerror.png)

Ezen felül volt még egy kozmetikai probléma, ami akkor áll elő, ha egy térképre kattintást igénylő lépést kezdeményezel, de utána ehelyett egy másik, ezt nem igénylő lépésre váltasz. Ilyenkor a képernyőn ragadhatnak a térképre kattintás GUI elemei, és egész addig nem tűnnek el, amíg valaki egy ilyen lépést végre nem hajt.

## Használhatóság

### Felhasználói felület

Ez a rész arra fókuszál, hogy kap-e a felhasználó elegendő és érthető visszajelzést a lépéseiről és azok kimeneteléről, illetve hogy mennyire felhasználóbarát a játék kezelőfelülete. Az első részre a válasz vegyes. Arról kapunk egyértelmű visszajelzést, hogy a lépésünk sikeres volt-e, vagy sikertelen, de az indoklás, hogy miért, azt nem látjuk semmilyen visszajelzésben.

Ezen kívül egy feltűnő hiányosság, hogy a játék vége után nincs mód visszatérni a főmenübe, és egy új játékot kezdeni. Ez csak a program újraindításával lehetséges.

### Tanulhatóság

Itt a kérdés az, hogy milyen könnyen sajátítható el a játék. Az alapvetően intuitív, hogy a különböző inputok mit csinálnak, viszont a játék leírásához nincsen beépített súgó, ez csak a dokumentációban van részletesen leírva.

### Kiegyenlítettség

Az utolsó szempont pedig az, hogy mennyire könnyű kiegyenlítetlen játékhelyzetet előállítani. A dokumentációban le van írva, hogy a két csapat játékosainak száma között maximum 1 legyen az eltérés, viszont ez a programban semmilyen módon nincs beépítve. Nincs figyelmeztetés vagy blokkolás, ha ennek nem megfelelő beállításokkal indítasz el egy meccset.
Binary file added doc/pipeerror.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/playgame.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/startup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 9462c97

Please sign in to comment.