diff --git a/code/Herzschlag/build.gradle b/code/Herzschlag/build.gradle index ac770a2..e59a085 100644 --- a/code/Herzschlag/build.gradle +++ b/code/Herzschlag/build.gradle @@ -17,6 +17,8 @@ repositories { } dependencies { + implementation 'junit:junit:4.13.1' + // Junit 5 dependencies testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.+' testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.+' diff --git a/code/Herzschlag/src/main/java/ch/zhaw/prog2/heartbeat/Heart.java b/code/Herzschlag/src/main/java/ch/zhaw/prog2/heartbeat/Heart.java index d7df62c..19eae26 100644 --- a/code/Herzschlag/src/main/java/ch/zhaw/prog2/heartbeat/Heart.java +++ b/code/Herzschlag/src/main/java/ch/zhaw/prog2/heartbeat/Heart.java @@ -65,8 +65,39 @@ public class Heart { * InvalidValvePositionException occurs during diastole or systole * TODO Implement a pause mechanism based on the current heart rate */ - public void executeHeartBeat() throws HeartBeatDysfunctionException{ + public void executeHeartBeat() throws HeartBeatDysfunctionException { //TODO implement + for(int i = 0; i < 2; i ++){ + if(state == State.DIASTOLE) { + try { + executeDiastole(); + } catch (Valve.IllegalValveStateException e) { + e.printStackTrace(); + throw new HeartBeatDysfunctionException(e.getMessage()); + } catch (InvalidValvePositionException e) { + e.printStackTrace(); + throw new HeartBeatDysfunctionException(e.getMessage()); + } + } + else if(state == State.SYSTOLE){ + try { + executeSystole(); + } catch (Valve.IllegalValveStateException e) { + e.printStackTrace(); + throw new HeartBeatDysfunctionException(e.getMessage()); + } catch (InvalidValvePositionException e) { + e.printStackTrace(); + throw new HeartBeatDysfunctionException(e.getMessage()); + } + } + } + + try { + Thread.currentThread().sleep((long) (1.0*heartRate/60.0*1000.0)); + System.out.println("wait:" + (1.0*heartRate/60*1000)); + } catch (InterruptedException e) { + e.printStackTrace(); + } } /** @@ -74,8 +105,35 @@ public class Heart { * * @throws Valve.IllegalValveStateException when one of the valves has an illegal State */ - public void executeDiastole() { + public void executeDiastole() throws Valve.IllegalValveStateException, InvalidValvePositionException { //TODO implement + //Segelklappen ("atrioventricular valves") öffnen + for(Half half : halves) { + if(half.isAtrioventricularValveOpen()){ + throw new InvalidValvePositionException(); + } + half.openAtrioventricularValve(); + } + + //Taschenklappen ("semilunar valves") schliessen + for(Half half : halves) { + if(!half.isSemilunarValveOpen()){ + throw new InvalidValvePositionException(); + } + half.closeSemilunarValve(); + } + + //Vorhöfe ("atria") entspannen + for(Half half : halves) { + half.relaxAtrium(); + } + + //Herzkammern ("ventricle") entspannen + for(Half half : halves) { + half.relaxVentricle(); + } + + state = State.SYSTOLE; } /** @@ -83,8 +141,36 @@ public class Heart { * * @throws Valve.IllegalValveStateException when one of the valves has an illegal State */ - public void executeSystole() { + public void executeSystole() throws Valve.IllegalValveStateException, InvalidValvePositionException { //TODO implement + + //Segelklappen schliessen + for(Half half : halves) { + if(!half.isAtrioventricularValveOpen()){ + throw new InvalidValvePositionException(); + } + half.closeAtrioventricularValve(); + } + + //Taschenklappen öffnen + for(Half half : halves) { + if(half.isSemilunarValveOpen()){ + throw new InvalidValvePositionException(); + } + half.openSemilunarValve(); + } + + //Herzkammern kontrahieren + for(Half half : halves) { + half.contractAtrium(); + } + + //Vorhöfe kontrahieren + for(Half half : halves) { + half.contractVentricle(); + } + + state = State.DIASTOLE; } public State getState() { @@ -138,8 +224,22 @@ public class Heart { * * @param args */ - public static void main(String[] args) throws HeartBeatDysfunctionException { + public static void main(String[] args) throws HeartBeatDysfunctionException, Valve.IllegalValveStateException, InvalidValvePositionException { Heart heart = new Heart(); heart.executeHeartBeat(); } + + public static class InvalidValvePositionException extends Exception { + + public InvalidValvePositionException() { + } + + public InvalidValvePositionException(String message) { + super(message); + } + + public InvalidValvePositionException(String message, Throwable cause) { + super(message, cause); + } + } } diff --git a/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/HeartTest.java b/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/HeartTest.java index d3b7968..89f4838 100644 --- a/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/HeartTest.java +++ b/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/HeartTest.java @@ -7,11 +7,22 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import ch.zhaw.prog2.heartbeat.parts.Valve; +import org.junit.Before; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import ch.zhaw.prog2.heartbeat.Heart.State; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnitRunner; +@RunWith(MockitoJUnitRunner.class) class HeartTest { /** * This is a very simple test to check if Junit and Mockito are properly set up. @@ -26,7 +37,7 @@ class HeartTest { * Tests a single heartbeat */ @Test - void testHeartBeat() throws Heart.HeartBeatDysfunctionException { + void testHeartBeat() throws Heart.HeartBeatDysfunctionException, Valve.IllegalValveStateException, Heart.InvalidValvePositionException { Heart heart = new Heart(); State startState = heart.getState(); @@ -40,7 +51,7 @@ class HeartTest { * Tests if the valves are open or closed depending on the status of the heart */ @Test - void testValveStatus() throws Heart.HeartBeatDysfunctionException { + void testValveStatus() throws Heart.HeartBeatDysfunctionException, Valve.IllegalValveStateException, Heart.InvalidValvePositionException { Heart heart = new Heart(); heart.executeHeartBeat(); @@ -78,9 +89,15 @@ class HeartTest { * with exception Stubbing */ @Test - void testExecuteHartBeatErrorBehaviourWithStubbing() throws Valve.IllegalValveStateException { + void testExecuteHartBeatErrorBehaviourWithStubbing() { //TODO implement - fail(); + Half half = spy(new Half(Half.Side.LEFT)); + Heart heart = new Heart(half, new Half(Half.Side.RIGHT)); + half.initializeState(heart.getState()); + when(half.isAtrioventricularValveOpen()).thenReturn(false); + + assertThrows(Heart.HeartBeatDysfunctionException .class, // verification using lambda + () -> heart.executeHeartBeat()); } /** @@ -92,9 +109,77 @@ class HeartTest { * */ @Test - void testValvesBehavior() { + void testValvesBehavior() throws Valve.IllegalValveStateException, Heart.HeartBeatDysfunctionException { //TODO implement - fail(); + Half halfLeft = spy(new Half(Half.Side.LEFT)); + Half halfRight = spy(new Half(Half.Side.RIGHT)); + Heart heart = new Heart(halfLeft, halfRight); + + heart.executeHeartBeat(); + + InOrder inOrderHalfLeft = inOrder(halfLeft); + + inOrderHalfLeft.verify(halfLeft).openAtrioventricularValve(); + inOrderHalfLeft.verify(halfLeft).closeSemilunarValve(); + inOrderHalfLeft.verify(halfLeft).relaxAtrium(); + inOrderHalfLeft.verify(halfLeft).relaxVentricle(); + + inOrderHalfLeft.verify(halfLeft).closeAtrioventricularValve(); + inOrderHalfLeft.verify(halfLeft).openSemilunarValve(); + inOrderHalfLeft.verify(halfLeft).contractAtrium(); + inOrderHalfLeft.verify(halfLeft).contractVentricle(); + + inOrderHalfLeft.verifyNoMoreInteractions(); + + InOrder inOrderHalfRight = inOrder(halfRight); + + inOrderHalfRight.verify(halfRight).openAtrioventricularValve(); + inOrderHalfRight.verify(halfRight).closeSemilunarValve(); + inOrderHalfRight.verify(halfRight).relaxAtrium(); + inOrderHalfRight.verify(halfRight).relaxVentricle(); + + inOrderHalfRight.verify(halfRight).closeAtrioventricularValve(); + inOrderHalfRight.verify(halfRight).openSemilunarValve(); + inOrderHalfRight.verify(halfRight).contractAtrium(); + inOrderHalfRight.verify(halfRight).contractVentricle(); + + inOrderHalfRight.verifyNoMoreInteractions(); + } + @Test + void testDiastoleExceptionAtrioventricularValve(){ + Half half = spy(new Half(Half.Side.LEFT)); + Heart heart = new Heart(half, new Half(Half.Side.RIGHT)); + when(half.isAtrioventricularValveOpen()).thenReturn(true); + assertThrows(Heart.InvalidValvePositionException .class, // verification using lambda + () -> heart.executeDiastole()); + } + + @Test + void testDiastoleExceptionSemilunarValve(){ + Half half = spy(new Half(Half.Side.LEFT)); + Heart heart = new Heart(half, new Half(Half.Side.RIGHT)); + when(half.isSemilunarValveOpen()).thenReturn(false); + assertThrows(Heart.InvalidValvePositionException .class, // verification using lambda + () -> heart.executeDiastole()); + } + + @Test + void testSystoleExceptionAtrioventricularValve(){ + Half half = spy(new Half(Half.Side.LEFT)); + Heart heart = new Heart(half, new Half(Half.Side.RIGHT)); + when(half.isAtrioventricularValveOpen()).thenReturn(false); + assertThrows(Heart.InvalidValvePositionException .class, // verification using lambda + () -> heart.executeSystole()); + } + + @Test + void testSystoleExceptionSemilunarValve(){ + Half half = spy(new Half(Half.Side.LEFT)); + Heart heart = new Heart(half, new Half(Half.Side.RIGHT)); + when(half.isSemilunarValveOpen()).thenReturn(true); + assertThrows(Heart.InvalidValvePositionException .class, // verification using lambda + () -> heart.executeSystole()); + } } diff --git a/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/PacemakerTest.java b/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/PacemakerTest.java index 52d353f..b8d05f1 100644 --- a/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/PacemakerTest.java +++ b/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/PacemakerTest.java @@ -1,6 +1,8 @@ package ch.zhaw.prog2.heartbeat; import org.junit.jupiter.api.Test; +import org.mockito.Mock; + import static org.junit.jupiter.api.Assertions.*; /* @@ -8,13 +10,25 @@ import static org.junit.jupiter.api.Assertions.*; */ public class PacemakerTest { + @Mock + Pacemaker pacemaker = new Pacemaker(new Heart()); + /** * Test if setHeartRate does throw correct exception when rate is rejected (because frequency is out of range) */ @Test void testSetHeartRateRejectsFrequenciesOutOfRange() { //TODO implement - fail(); + for(int i = -10; i < 29; i ++){ + int finalI = i; + assertThrows(IllegalArgumentException .class, // verification using lambda + () -> pacemaker.setHeartRate(finalI)); + } + for(int i = 221; i < 230; i ++){ + int finalI1 = i; + assertThrows(IllegalArgumentException .class, // verification using lambda + () -> pacemaker.setHeartRate(finalI1)); + } } @@ -24,7 +38,9 @@ public class PacemakerTest { @Test void testSetHeartRateAppliesFrequenciesInsideRange() { //TODO implement - fail(); + for(int i = 30; i <= 220; i ++){ + assertEquals(i, pacemaker.setHeartRate(i)); + } } }