diff --git a/logs/hippodrome.log b/logs/hippodrome.log
new file mode 100644
index 00000000..59825894
--- /dev/null
+++ b/logs/hippodrome.log
@@ -0,0 +1,92 @@
+2023-01-23 20:26:39,509 DEBUG Horse Создание Horse, имя name, скорость 1.0
+2023-01-23 20:26:39,666 DEBUG Horse Создание Horse, имя name, скорость 1.0
+2023-01-23 20:26:39,700 DEBUG Horse Создание Horse, имя name, скорость 1.0
+2023-01-23 20:27:48,062 DEBUG Horse Создание Horse, имя name, скорость 1.0
+2023-01-23 20:27:48,162 DEBUG Horse Создание Horse, имя name, скорость 1.0
+2023-01-23 20:27:48,185 DEBUG Horse Создание Horse, имя name, скорость 1.0
+2023-01-23 20:29:33,579 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 20:40:19,243 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 20:42:34,775 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 20:43:20,722 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 20:46:15,850 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 20:47:33,457 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 20:50:05,310 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 20:52:06,591 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 20:55:32,274 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 20:56:30,748 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 20:57:14,309 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 21:09:05,605 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 21:09:45,544 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 21:11:07,629 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 21:16:01,626 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 21:17:22,602 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 21:18:00,968 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 21:19:02,925 DEBUG Hippodrome Создание Hippodrome, лошадей 5
+2023-01-23 21:32:54,628 DEBUG Hippodrome Создание Hippodrome, лошадей 5
+2023-01-23 21:34:55,961 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 21:35:19,952 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 21:36:33,614 DEBUG Hippodrome Создание Hippodrome, лошадей 50
+2023-01-23 21:36:33,882 ERROR Hippodrome Horses list is null
+2023-01-23 21:36:33,896 DEBUG Horse Создание Horse, имя Horse, скорость 0.6335314534697963
+2023-01-23 21:36:33,896 DEBUG Horse Создание Horse, имя Horse, скорость 0.43009176892586454
+2023-01-23 21:36:33,896 DEBUG Horse Создание Horse, имя Horse, скорость 0.507182091009049
+2023-01-23 21:36:33,896 DEBUG Horse Создание Horse, имя Horse, скорость 0.9158620498480842
+2023-01-23 21:36:33,897 DEBUG Horse Создание Horse, имя Horse, скорость 0.18568932867359256
+2023-01-23 21:36:33,897 DEBUG Horse Создание Horse, имя Horse, скорость 0.31965021793605297
+2023-01-23 21:36:33,897 DEBUG Horse Создание Horse, имя Horse, скорость 0.52078124036609
+2023-01-23 21:36:33,897 DEBUG Horse Создание Horse, имя Horse, скорость 0.9981569725941888
+2023-01-23 21:36:33,897 DEBUG Horse Создание Horse, имя Horse, скорость 0.9198946243355042
+2023-01-23 21:36:33,898 DEBUG Horse Создание Horse, имя Horse, скорость 0.6006654666722108
+2023-01-23 21:36:33,898 DEBUG Horse Создание Horse, имя Horse, скорость 0.8631358256598722
+2023-01-23 21:36:33,898 DEBUG Horse Создание Horse, имя Horse, скорость 0.9946370795427241
+2023-01-23 21:36:33,898 DEBUG Horse Создание Horse, имя Horse, скорость 0.14566065528860106
+2023-01-23 21:36:33,898 DEBUG Horse Создание Horse, имя Horse, скорость 0.4645926180164245
+2023-01-23 21:36:33,898 DEBUG Horse Создание Horse, имя Horse, скорость 0.8281699580072763
+2023-01-23 21:36:33,899 DEBUG Horse Создание Horse, имя Horse, скорость 0.06980829103182662
+2023-01-23 21:36:33,899 DEBUG Horse Создание Horse, имя Horse, скорость 0.004193813526336743
+2023-01-23 21:36:33,899 DEBUG Horse Создание Horse, имя Horse, скорость 0.9379561101586087
+2023-01-23 21:36:33,899 DEBUG Horse Создание Horse, имя Horse, скорость 0.40006395297439123
+2023-01-23 21:36:33,899 DEBUG Horse Создание Horse, имя Horse, скорость 0.4446705315787328
+2023-01-23 21:36:33,899 DEBUG Horse Создание Horse, имя Horse, скорость 0.5119509013102479
+2023-01-23 21:36:33,899 DEBUG Horse Создание Horse, имя Horse, скорость 0.6831245388519113
+2023-01-23 21:36:33,900 DEBUG Horse Создание Horse, имя Horse, скорость 0.4540684075608016
+2023-01-23 21:36:33,900 DEBUG Horse Создание Horse, имя Horse, скорость 0.36305019132695915
+2023-01-23 21:36:33,900 DEBUG Horse Создание Horse, имя Horse, скорость 0.9431244490655691
+2023-01-23 21:36:33,900 DEBUG Horse Создание Horse, имя Horse, скорость 0.29523972353405015
+2023-01-23 21:36:33,900 DEBUG Horse Создание Horse, имя Horse, скорость 0.8763249864233851
+2023-01-23 21:36:33,900 DEBUG Horse Создание Horse, имя Horse, скорость 0.915415409127704
+2023-01-23 21:36:33,900 DEBUG Horse Создание Horse, имя Horse, скорость 0.7737126148077987
+2023-01-23 21:36:33,901 DEBUG Horse Создание Horse, имя Horse, скорость 0.8804573488711275
+2023-01-23 21:36:33,901 DEBUG Hippodrome Создание Hippodrome, лошадей 30
+2023-01-23 21:36:33,912 ERROR Hippodrome Horses list is empty
+2023-01-23 21:36:33,924 DEBUG Horse Создание Horse, имя Horse, скорость 0.9503494505122779
+2023-01-23 21:36:33,925 DEBUG Horse Создание Horse, имя Horse, скорость 0.6303306836602167
+2023-01-23 21:36:33,925 DEBUG Horse Создание Horse, имя Horse, скорость 0.6598296844232557
+2023-01-23 21:36:33,925 DEBUG Horse Создание Horse, имя Horse, скорость 0.9506544904478381
+2023-01-23 21:36:33,926 DEBUG Horse Создание Horse, имя Horse, скорость 0.6078338359237819
+2023-01-23 21:36:33,926 DEBUG Horse Создание Horse, имя Horse, скорость 0.9937066968724008
+2023-01-23 21:36:33,926 DEBUG Horse Создание Horse, имя Horse, скорость 0.17291377699724453
+2023-01-23 21:36:33,927 DEBUG Horse Создание Horse, имя Horse, скорость 0.9197608569717186
+2023-01-23 21:36:33,927 DEBUG Horse Создание Horse, имя Horse, скорость 0.39142348750622524
+2023-01-23 21:36:33,927 DEBUG Horse Создание Horse, имя Horse, скорость 0.30600190830046115
+2023-01-23 21:36:33,927 DEBUG Horse Создание Horse, имя Horse, скорость 0.26448749884138545
+2023-01-23 21:36:33,928 DEBUG Horse Создание Horse, имя Horse, скорость 0.7368698996309604
+2023-01-23 21:36:33,928 DEBUG Horse Создание Horse, имя Horse, скорость 0.22712554954974662
+2023-01-23 21:36:33,928 DEBUG Horse Создание Horse, имя Horse, скорость 0.5375320951215063
+2023-01-23 21:36:33,929 DEBUG Horse Создание Horse, имя Horse, скорость 0.6831282174689517
+2023-01-23 21:36:33,929 DEBUG Horse Создание Horse, имя Horse, скорость 0.44128564494737577
+2023-01-23 21:36:33,929 DEBUG Horse Создание Horse, имя Horse, скорость 0.35400514708723596
+2023-01-23 21:36:33,929 DEBUG Horse Создание Horse, имя Horse, скорость 0.09204394201249877
+2023-01-23 21:36:33,929 DEBUG Horse Создание Horse, имя Horse, скорость 0.8163041089517054
+2023-01-23 21:36:33,930 DEBUG Horse Создание Horse, имя Horse, скорость 0.6746622436796472
+2023-01-23 21:36:33,930 DEBUG Horse Создание Horse, имя Horse, скорость 0.008825241739211953
+2023-01-23 21:36:33,930 DEBUG Horse Создание Horse, имя Horse, скорость 0.638709086637461
+2023-01-23 21:36:33,930 DEBUG Horse Создание Horse, имя Horse, скорость 0.6797320166077224
+2023-01-23 21:36:33,930 DEBUG Horse Создание Horse, имя Horse, скорость 0.43539162273187204
+2023-01-23 21:36:33,930 DEBUG Horse Создание Horse, имя Horse, скорость 0.713286581894386
+2023-01-23 21:36:33,930 DEBUG Horse Создание Horse, имя Horse, скорость 0.42269491110084867
+2023-01-23 21:36:33,930 DEBUG Horse Создание Horse, имя Horse, скорость 0.02691366933446837
+2023-01-23 21:36:33,931 DEBUG Horse Создание Horse, имя Horse, скорость 0.610396284776596
+2023-01-23 21:36:33,931 DEBUG Horse Создание Horse, имя Horse, скорость 0.26152427505107523
+2023-01-23 21:36:33,931 DEBUG Horse Создание Horse, имя Horse, скорость 0.7144681052093862
+2023-01-23 21:36:33,931 DEBUG Hippodrome Создание Hippodrome, лошадей 30
diff --git a/pom.xml b/pom.xml
index a0a25572..693e5f3d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,56 @@
-
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.9.0
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ 5.8.2
+ test
+
+
+ org.mockito
+ mockito-core
+ 4.11.0
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ 4.2.0
+ test
+
+
+ org.mockito
+ mockito-inline
+ 4.2.0
+ test
+
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.19.0
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.19.0
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ 2.19.0
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.36
+
\ No newline at end of file
diff --git a/src/main/java/Hippodrome.java b/src/main/java/Hippodrome.java
index f1a4abb2..261e40e9 100644
--- a/src/main/java/Hippodrome.java
+++ b/src/main/java/Hippodrome.java
@@ -1,3 +1,6 @@
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -6,16 +9,20 @@
public class Hippodrome {
+ private static final Logger logger = LoggerFactory.getLogger(Hippodrome.class);
+
private final List horses;
public Hippodrome(List horses) {
if (isNull(horses)) {
+ logger.error("Horses list is null");
throw new IllegalArgumentException("Horses cannot be null.");
} else if (horses.isEmpty()) {
+ logger.error("Horses list is empty");
throw new IllegalArgumentException("Horses cannot be empty.");
}
-
this.horses = horses;
+ logger.debug("Создание Hippodrome, лошадей {}", horses.size());
}
public List getHorses() {
diff --git a/src/main/java/Horse.java b/src/main/java/Horse.java
index dbf05c34..5177ddc4 100644
--- a/src/main/java/Horse.java
+++ b/src/main/java/Horse.java
@@ -1,27 +1,37 @@
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import static java.util.Objects.isNull;
public class Horse {
+ private static final Logger logger = LoggerFactory.getLogger(Horse.class);
+
private final String name;
private final double speed;
private double distance;
public Horse(String name, double speed, double distance) {
if (isNull(name)) {
+ logger.error("Name is null");
throw new IllegalArgumentException("Name cannot be null.");
} else if (name.isBlank()) {
+ logger.error("Name is blank");
throw new IllegalArgumentException("Name cannot be blank.");
}
if (speed < 0) {
+ logger.error("Speed is negative");
throw new IllegalArgumentException("Speed cannot be negative.");
}
if (distance < 0) {
+ logger.error("Distance is negative");
throw new IllegalArgumentException("Distance cannot be negative.");
}
this.name = name;
this.speed = speed;
this.distance = distance;
+ logger.debug("Создание Horse, имя {}, скорость {}", name, speed);
}
public Horse(String name, double speed) {
diff --git a/src/main/java/Main.java b/src/main/java/Main.java
index 89417f76..63d1ca3f 100644
--- a/src/main/java/Main.java
+++ b/src/main/java/Main.java
@@ -1,9 +1,15 @@
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.util.List;
import java.util.concurrent.TimeUnit;
public class Main {
+ private static final Logger logger = LoggerFactory.getLogger(Main.class);
+
public static void main(String[] args) throws Exception {
+
List horses = List.of(
new Horse("Буцефал", 2.4),
new Horse("Туз Пик", 2.5),
@@ -14,7 +20,7 @@ public static void main(String[] args) throws Exception {
new Horse("Вишня", 3)
);
Hippodrome hippodrome = new Hippodrome(horses);
-
+ logger.info("Начало скачек. Количество участников: {}", hippodrome.getHorses().size());
for (int i = 0; i < 100; i++) {
hippodrome.move();
watch(hippodrome);
@@ -23,6 +29,7 @@ public static void main(String[] args) throws Exception {
String winnerName = hippodrome.getWinner().getName();
System.out.println("Победил " + winnerName + "!");
+ logger.info("Окончание скачек. Победитель: {}", winnerName);
}
private static void watch(Hippodrome hippodrome) throws Exception {
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
new file mode 100644
index 00000000..57146986
--- /dev/null
+++ b/src/main/resources/log4j2.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+ %d %p %c{1.} %m%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/HippodromeTest.java b/src/test/java/HippodromeTest.java
new file mode 100644
index 00000000..6da8f4d0
--- /dev/null
+++ b/src/test/java/HippodromeTest.java
@@ -0,0 +1,78 @@
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+@ExtendWith(MockitoExtension.class)
+class HippodromeTest {
+
+ @Test
+ void hippodromeConstructorParameterIsNullShouldTrowIllegalArgumentExceptionWithMessageHorsesCannotBeNull() {
+ String message = "Horses cannot be null.";
+ Throwable exception = assertThrows(
+ IllegalArgumentException.class,
+ () -> new Hippodrome(null)
+ );
+ String expected = message;
+ String actual = exception.getMessage();
+ assertEquals(expected, actual);
+
+ }
+
+ @Test
+ void hippodromeConstructorParameterIsEmptyShouldTrowIllegalArgumentExceptionWithMessageHorsesCannotBeEmpty() {
+ String message = "Horses cannot be empty.";
+ Throwable exception = assertThrows(
+ IllegalArgumentException.class,
+ () -> new Hippodrome(new ArrayList<>())
+ );
+ String expected = message;
+ String actual = exception.getMessage();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ void getHorsesShouldReturnListHorsesParameterOfConstructor() {
+ List horses = new ArrayList<>();
+ for (int i = 0; i < 30; i++) {
+ horses.add(new Horse(Horse.class.getName(), Math.random(), Math.random()));
+ }
+ Hippodrome hippodrome = new Hippodrome(horses);
+ boolean expected = horses.equals(hippodrome.getHorses());
+ assertTrue(expected);
+ }
+
+ @Test
+ void moveShouldToBeCalledFromAllHorses() {
+ List horses = new ArrayList<>();
+ for (int i = 0; i < 50; i++) {
+ horses.add(mock(Horse.class));
+ }
+ Hippodrome hippodrome = new Hippodrome(horses);
+ hippodrome.move();
+ for (Horse hors : horses) {
+ verify(hors).move();
+ }
+ }
+
+ @Test
+ void getWinnerShouldReturnHorseWithGreatestDistance() {
+ List horses = new ArrayList<>();
+ for (int i = 0; i < 30; i++) {
+ horses.add(new Horse(Horse.class.getName(), Math.random(), Math.random()));
+ }
+ Hippodrome hippodrome = new Hippodrome(horses);
+ double expected = horses.stream().max(Comparator.comparingDouble(Horse::getDistance)).get().getDistance();
+ double actual = hippodrome.getWinner().getDistance();
+ assertEquals(expected, actual);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/HorseTest.java b/src/test/java/HorseTest.java
new file mode 100644
index 00000000..1d539a24
--- /dev/null
+++ b/src/test/java/HorseTest.java
@@ -0,0 +1,136 @@
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.MockedStatic;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.only;
+
+class HorseTest {
+ @Test
+ void horseConstructorNameIsNullShouldTrowIllegalArgumentException() {
+ Class expected = IllegalArgumentException.class;
+ assertThrows(expected, () -> new Horse(null, 0, 0));
+ }
+
+ @Test
+ void horseConstructorNameIsNullShouldSendMessageNameCannotBeNull() {
+ String expected = "Name cannot be null.";
+ try {
+ new Horse(null, 0, 0);
+ } catch (IllegalArgumentException exception) {
+ String actual = exception.getMessage();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " ", "\n", "\t"})
+ void horseConstructorNameIsBlankShouldTrowIllegalArgumentException(String name) {
+ Class expected = IllegalArgumentException.class;
+ assertThrows(expected, () -> new Horse(name, 0, 0));
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " ", "\n", "\t"})
+ void horseConstructorNameIsBlankShouldSendMessageNameCannotBeBlank(String name) {
+ String expected = "Name cannot be blank.";
+ try {
+ new Horse(name, 0, 0);
+ } catch (IllegalArgumentException exception) {
+ String actual = exception.getMessage();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test()
+ void horseConstructorSpeedIsNegativeShouldTrowIllegalArgumentException() {
+ Class expected = IllegalArgumentException.class;
+ assertThrows(expected, () -> new Horse("name", -1, 0));
+ }
+
+ @Test
+ void horseConstructorSpeedIsNegativeShouldSendMessageSpeedCannotBeNegative() {
+ String expected = "Speed cannot be negative.";
+ try {
+ new Horse("name", -1, 0);
+ } catch (IllegalArgumentException exception) {
+ String actual = exception.getMessage();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ void horseConstructorDistanceIsNegativeShouldTrowIllegalArgumentException() {
+ Class expected = IllegalArgumentException.class;
+ assertThrows(expected, () -> new Horse("name", 0, -1));
+ }
+
+ @Test
+ void horseConstructorDistanceIsNegativeShouldSendMessageDistanceCannotBeNegative() {
+ String expected = "Distance cannot be negative.";
+ try {
+ new Horse("name", 0, -1);
+ } catch (IllegalArgumentException exception) {
+ String actual = exception.getMessage();
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ void getNameShouldReturnName() {
+ String name = "name";
+ Horse horse = new Horse(name, 0, 0);
+ String expected = name;
+ String actual = horse.getName();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ void getSpeedShouldReturnSpeed() {
+ double speed = 0;
+ Horse horse = new Horse("name", speed, 0);
+ double expected = speed;
+ double actual = horse.getSpeed();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ void getDistanceShouldReturnDistance() {
+ double distance = 0;
+ Horse horse = new Horse("name", 0, distance);
+ double expected = distance;
+ double actual = horse.getDistance();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ void getDistanceShouldReturnZero() {
+ Horse horse = new Horse("name", 0);
+ double expected = 0;
+ double actual = horse.getDistance();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ void moveShouldToCallGetRandomDouble() {
+ try (MockedStatic horseMockedStatic = mockStatic(Horse.class)) {
+ new Horse("name", 0, 0).move();
+ horseMockedStatic.verify(() -> Horse.getRandomDouble(0.2, 0.9), only());
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(doubles = {1.0, 2.0, 3.0})
+ void moveShouldAssignValueToDistanceField(double value) {
+ try (MockedStatic horseMockedStatic = mockStatic(Horse.class)) {
+ horseMockedStatic.when(() -> Horse.getRandomDouble(0.2, 0.9)).thenReturn(value);
+ Horse horse = new Horse("name", 1, 0);
+ horse.move();
+ double expected = horse.getDistance();
+ assertEquals(expected, Horse.getRandomDouble(0.2, 0.9));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/MainTest.java b/src/test/java/MainTest.java
new file mode 100644
index 00000000..ce2aedc2
--- /dev/null
+++ b/src/test/java/MainTest.java
@@ -0,0 +1,12 @@
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+
+class MainTest {
+ @Test
+ @Disabled("If necessary, run manually")
+ @Timeout(value = 22)
+ void mainRunsForNoMoreThan22Seconds() throws Exception {
+ Main.main(new String[0]);
+ }
+}
\ No newline at end of file