Skip to content

Commit

Permalink
Feature/add tests (#6)
Browse files Browse the repository at this point in the history
* parameterized test configured

* checkstyle config

* new formatting applied

* Util class converted into service

* sonar exclusions optimized

* sonar exclusions optimized
  • Loading branch information
maemresen committed May 8, 2024
1 parent 8372a9e commit 475797b
Show file tree
Hide file tree
Showing 18 changed files with 625 additions and 1,443 deletions.
1,340 changes: 0 additions & 1,340 deletions .editorconfig

This file was deleted.

24 changes: 24 additions & 0 deletions .run/Sonar Scan.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Sonar Scan" type="GradleRunConfiguration" factoryName="Gradle" folderName="00-build">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-Dsonar.branch.name=local" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="sonar" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ sonar {
property("sonar.projectKey", "maeworkshop_k8s-workshop")
property("sonar.organization", "maeworkshop")
property("sonar.host.url", "https://sonarcloud.io")
property("sonar.verbose", "true")
property("sonar.coverage.jacoco.xmlReportPaths", "**/build/reports/jacoco/test/jacocoTestReport.xml")
}
}
Expand Down Expand Up @@ -59,6 +60,7 @@ subprojects {

withType<Test> {
useJUnitPlatform()
jvmArgs("-XX:+EnableDynamicAgentLoading")
}

named("check") {
Expand Down
382 changes: 382 additions & 0 deletions config/checkstyle/checkstyle.xml

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions module/app/k8s-workshop-data-generator/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ val confluentVersion = "7.6.1"
val springCloudVersion = "2023.0.0"
val lombokVersion = "1.18.30"

tasks {
withType<JacocoReport> {
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.map {
fileTree(it) {
exclude(listOf("**/config/**/*"))
}
}))
}
}
}

repositories {
maven {
setUrl("https://packages.confluent.io/maven/")
Expand All @@ -33,6 +45,7 @@ dependencies {
implementation(project(":module:lib:k8s-workshop-messaging-spring-boot-starter"))

testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.junit.jupiter:junit-jupiter-params")
testImplementation("org.assertj:assertj-core")

compileOnly("org.projectlombok:lombok:$lombokVersion")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.maemresen.k8s.workshop.data.generator.config.props;

import com.maemresen.lib.message.dto.SensorType;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ConfigurationProperties(prefix = "app.generator.constraint")
@Configuration
public class GeneratorConstraintProps {
private Map<SensorType, Double> minValues;
private Map<SensorType, Double> maxValues;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.maemresen.k8s.workshop.data.generator.config.props;

import java.util.List;
import com.maemresen.lib.message.dto.SensorType;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -15,7 +15,7 @@
@AllArgsConstructor
@ConfigurationProperties(prefix = "app.generator.sensor-data")
@Configuration
public class SensorDataGeneratorProps {
public class GeneratorSensorDataProps {

private List<LocationProps> locations;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.maemresen.k8s.workshop.data.generator.messaging;

import com.maemresen.lib.message.dto.SensorData;
import com.maemresen.k8s.workshop.messaging.starter.BaseMessageProducer;
import com.maemresen.k8s.workshop.messaging.starter.MessagingProps;
import com.maemresen.k8s.workshop.messaging.starter.Topic;
import com.maemresen.lib.message.dto.SensorData;
import org.springframework.cloud.function.cloudevent.CloudEventMessageBuilder;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.maemresen.k8s.workshop.data.generator.service;

import com.maemresen.k8s.workshop.data.generator.config.props.GeneratorConstraintProps;
import com.maemresen.lib.message.dto.Device;
import com.maemresen.lib.message.dto.Sensor;
import com.maemresen.lib.message.dto.SensorData;
import com.maemresen.lib.message.dto.SensorType;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Random;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class SensorDataGeneratorService {

private final GeneratorConstraintProps generatorConstraintProps;
private final Random random = new SecureRandom();

public SensorData generateRandomSensorData(
final String locationName,
final String deviceName,
final String sensorName,
final SensorType sensorType) {
if (sensorType == null) {
throw new IllegalArgumentException("SensorType cannot be null");
}

final Device device = Device.newBuilder()
.setDeviceId(deviceName)
.setLocation(locationName)
.build();

final Sensor sensor = Sensor.newBuilder()
.setSensorId(sensorName)
.setType(sensorType)
.build();

return SensorData.newBuilder()
.setDevice(device)
.setSensor(sensor)
.setTimestamp(System.currentTimeMillis())
.setValue(getRandomValueBySensorType(sensorType))
.build();
}

private double getRandomValueBySensorType(final SensorType sensorType) {
final double minValue = getMinValueBySensorType(sensorType);
final double maxValue = getMaxValueBySensorType(sensorType);
return random.nextDouble() * (maxValue - minValue) + minValue;
}

private double getMinValueBySensorType(final SensorType sensorType) {
final Map<SensorType, Double> minValues = generatorConstraintProps.getMinValues();
if (minValues.containsKey(sensorType)) {
return minValues.get(sensorType);
}

throw new IllegalArgumentException("Sensor type " + sensorType + " is not supported");
}

private double getMaxValueBySensorType(final SensorType sensorType) {
final Map<SensorType, Double> maxValues = generatorConstraintProps.getMaxValues();
if (maxValues.containsKey(sensorType)) {
return maxValues.get(sensorType);
}

throw new IllegalArgumentException("Sensor type " + sensorType + " is not supported");
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.maemresen.k8s.workshop.data.generator.task;

import com.maemresen.k8s.workshop.data.generator.config.props.SensorDataGeneratorProps;
import com.maemresen.k8s.workshop.data.generator.config.props.GeneratorSensorDataProps;
import com.maemresen.k8s.workshop.data.generator.messaging.SensorDataProducer;
import com.maemresen.k8s.workshop.data.generator.util.SensorDataGeneratorUtil;
import com.maemresen.k8s.workshop.data.generator.service.SensorDataGeneratorService;
import com.maemresen.lib.message.dto.SensorData;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -14,16 +14,17 @@
@Component
public class DataGeneratorTask {

private final SensorDataGeneratorProps dataGeneratorProps;
private final GeneratorSensorDataProps dataGeneratorProps;
private final SensorDataProducer sensorDataProducer;
private final SensorDataGeneratorService sensorDataGeneratorService;

@Scheduled(cron = "0/2 * * * * ?")
public void produceSensorData() {

dataGeneratorProps.getLocations().forEach(location -> location.devices().forEach(
device -> device.sensors()
.forEach(sensor -> {
final SensorData sensorData = SensorDataGeneratorUtil.generateRandomSensorData(
final SensorData sensorData = sensorDataGeneratorService.generateRandomSensorData(
location.name(),
device.name(),
sensor.name(),
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ spring:

app:
generator:
constraint:
min-values:
TEMP: 20.0
HUMIDITY: 30.0
max-values:
TEMP: 35.0
HUMIDITY: 100.0
sensor-data:
locations:
- name: location1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.maemresen.k8s.workshop.data.generator.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.InstanceOfAssertFactories.DOUBLE;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.maemresen.k8s.workshop.data.generator.config.props.GeneratorConstraintProps;
import com.maemresen.lib.message.dto.SensorData;
import com.maemresen.lib.message.dto.SensorType;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class SensorDataGeneratorServiceTest {

private static final SensorType VALID_SENSOR_TYPE = SensorType.TEMP;
private static final double MIN_VALUE = 20.0;
private static final double MAX_VALUE = 35.0;

private static final Map<SensorType, Double> MIN_VALUES = Map.of(VALID_SENSOR_TYPE, MIN_VALUE);
private static final Map<SensorType, Double> MAX_VALUES = Map.of(VALID_SENSOR_TYPE, MAX_VALUE);

private static final Map<SensorType, Double> MIN_VALUES_WITHOUT_SENSOR_TYPE = new HashMap<>();
private static final Map<SensorType, Double> MAX_VALUES_WITHOUT_SENSOR_TYPE = new HashMap<>();

private static final String LOCATION_NAME = "Location";
private static final String DEVICE_NAME = "Device";
private static final String SENSOR_NAME = "Sensor";

@Mock
private GeneratorConstraintProps generatorConstraintProps;

@InjectMocks
private SensorDataGeneratorService sensorDataGeneratorService;

@Test
void generateRandomSensorData_shouldGenerateSensorValueWithinRange() {
when(generatorConstraintProps.getMinValues()).thenReturn(MIN_VALUES);
when(generatorConstraintProps.getMaxValues()).thenReturn(MAX_VALUES);

final SensorData sensorData =
sensorDataGeneratorService.generateRandomSensorData(
LOCATION_NAME,
DEVICE_NAME,
SENSOR_NAME,
VALID_SENSOR_TYPE);
assertThat(sensorData).isNotNull()
.extracting(SensorData::getValue).asInstanceOf(DOUBLE)
.isBetween(MIN_VALUE, MAX_VALUE);
}

@Test
void generateRandomSensorData_shouldThrowErrorOnNullSensorType() {
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(
() -> sensorDataGeneratorService.generateRandomSensorData(LOCATION_NAME, DEVICE_NAME,
SENSOR_NAME, null));
}

@Test
void generateRandomSensorData_shouldThrowErrorOnInvalidSensorType() {
when(generatorConstraintProps.getMinValues()).thenReturn(
MIN_VALUES_WITHOUT_SENSOR_TYPE);
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(
() -> sensorDataGeneratorService.generateRandomSensorData(LOCATION_NAME, DEVICE_NAME,
SENSOR_NAME, VALID_SENSOR_TYPE));

when(generatorConstraintProps.getMinValues()).thenReturn(MIN_VALUES);
when(generatorConstraintProps.getMaxValues()).thenReturn(MAX_VALUES_WITHOUT_SENSOR_TYPE);
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(
() -> sensorDataGeneratorService.generateRandomSensorData(LOCATION_NAME, DEVICE_NAME,
SENSOR_NAME, VALID_SENSOR_TYPE));
}

}
Loading

0 comments on commit 475797b

Please sign in to comment.