hw4: finalize selenoid and ansible workflow with citrus tests

This commit is contained in:
2026-02-27 01:38:06 +03:00
parent c06e9a89f1
commit 7ddea2e997
36 changed files with 1171 additions and 122 deletions

75
citrus-tests/pom.xml Normal file
View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ru.kovbasa</groupId>
<artifactId>citrus-tests</artifactId>
<version>1.0-SNAPSHOT</version>
<name>citrus-tests</name>
<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<citrus.version>3.2.1</citrus.version>
<surefire.version>2.22.2</surefire.version>
<log4j2.version>2.25.1</log4j2.version>
<petstore.base.url>https://petstore.swagger.io</petstore.base.url>
<petstore.base.path>/v2</petstore.base.path>
</properties>
<dependencies>
<dependency>
<groupId>com.consol.citrus</groupId>
<artifactId>citrus-core</artifactId>
<version>${citrus.version}</version>
</dependency>
<dependency>
<groupId>com.consol.citrus</groupId>
<artifactId>citrus-http</artifactId>
<version>${citrus.version}</version>
</dependency>
<dependency>
<groupId>com.consol.citrus</groupId>
<artifactId>citrus-testng</artifactId>
<version>${citrus.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.15.0</version>
<configuration>
<release>${maven.compiler.release}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
<systemPropertyVariables>
<petstore.base.url>${petstore.base.url}</petstore.base.url>
<petstore.base.path>${petstore.base.path}</petstore.base.path>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,57 @@
package ru.kovbasa.citrus;
import com.consol.citrus.annotations.CitrusTest;
import com.consol.citrus.message.MessageType;
import com.consol.citrus.testng.spring.TestNGCitrusSpringSupport;
import org.springframework.http.HttpStatus;
import org.testng.annotations.Test;
import java.util.concurrent.ThreadLocalRandom;
import static com.consol.citrus.http.actions.HttpActionBuilder.http;
import static com.consol.citrus.validation.json.JsonPathMessageValidationContext.Builder.jsonPath;
public class PetstoreNegativeScenariosTest extends TestNGCitrusSpringSupport {
@CitrusTest
@Test(description = "GET /pet/{id} returns 404 for unknown id")
public void getMissingPetReturnsNotFound() {
long petId = ThreadLocalRandom.current().nextLong(1_000_000L, Integer.MAX_VALUE);
variable("petId", String.valueOf(petId));
run(http()
.client("petstoreClient")
.send()
.get("/pet/${petId}"));
run(http()
.client("petstoreClient")
.receive()
.response(HttpStatus.NOT_FOUND)
.message()
.validate(jsonPath().expression("$.message", "Pet not found")));
}
@CitrusTest
@Test(description = "POST /pet with malformed JSON returns 400")
public void createPetWithMalformedJsonReturnsError() {
run(http()
.client("petstoreClient")
.send()
.post("/pet")
.message()
.type(MessageType.JSON)
.header("Content-Type", "application/json")
.body("""
{
"id": 123456,
"name": "Broken pet",
"photoUrls": ["https://petstore.test/photo.jpg"]
"""));
run(http()
.client("petstoreClient")
.receive()
.response(HttpStatus.BAD_REQUEST));
}
}

View File

@@ -0,0 +1,81 @@
package ru.kovbasa.citrus;
import com.consol.citrus.annotations.CitrusTest;
import com.consol.citrus.message.MessageType;
import com.consol.citrus.testng.spring.TestNGCitrusSpringSupport;
import org.springframework.http.HttpStatus;
import org.testng.annotations.Test;
import java.util.concurrent.ThreadLocalRandom;
import static com.consol.citrus.http.actions.HttpActionBuilder.http;
import static com.consol.citrus.validation.json.JsonPathMessageValidationContext.Builder.jsonPath;
public class PetstorePositiveScenariosTest extends TestNGCitrusSpringSupport {
@CitrusTest
@Test(description = "POST /pet creates resource and GET /pet/{id} returns created pet")
public void createPetAndGetById() {
long petId = ThreadLocalRandom.current().nextLong(1_000_000L, Integer.MAX_VALUE);
String petName = "Rex-" + petId;
variable("petId", String.valueOf(petId));
variable("petName", petName);
run(http()
.client("petstoreClient")
.send()
.post("/pet")
.message()
.type(MessageType.JSON)
.header("Content-Type", "application/json")
.body("""
{
"id": ${petId},
"category": {
"id": 1,
"name": "Dogs"
},
"name": "${petName}",
"photoUrls": ["https://petstore.test/photo.jpg"],
"tags": [{
"id": 1,
"name": "api-test"
}],
"status": "available"
}
"""));
run(http()
.client("petstoreClient")
.receive()
.response(HttpStatus.OK)
.message()
.validate(jsonPath().expression("$.id", "${petId}"))
.validate(jsonPath().expression("$.name", "${petName}"))
.validate(jsonPath().expression("$.status", "available")));
run(http()
.client("petstoreClient")
.send()
.get("/pet/${petId}"));
run(http()
.client("petstoreClient")
.receive()
.response(HttpStatus.OK)
.message()
.validate(jsonPath().expression("$.id", "${petId}"))
.validate(jsonPath().expression("$.name", "${petName}")));
run(http()
.client("petstoreClient")
.send()
.delete("/pet/${petId}"));
run(http()
.client("petstoreClient")
.receive()
.response(HttpStatus.OK));
}
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:citrus="http://www.citrusframework.org/schema/config"
xmlns:citrus-http="http://www.citrusframework.org/schema/http/config"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.citrusframework.org/schema/config http://www.citrusframework.org/schema/config/citrus-config.xsd
http://www.citrusframework.org/schema/http/config http://www.citrusframework.org/schema/http/config/citrus-http-config.xsd">
<context:property-placeholder location="classpath:citrus.properties"/>
<citrus:global-variables>
<citrus:file path="classpath:citrus.properties"/>
</citrus:global-variables>
<citrus-http:client id="petstoreClient"
request-url="${petstore.base.url}${petstore.base.path}"
timeout="10000"/>
</beans>

View File

@@ -0,0 +1,5 @@
default.test.author=spawn
default.test.package=ru.kovbasa.citrus
petstore.base.url=https://petstore.swagger.io
petstore.base.path=/v2

View File

@@ -0,0 +1,11 @@
status = WARN
name = citrus-log4j2
appender.console.type = Console
appender.console.name = Console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{HH:mm:ss.SSS} %-5p %c{1} - %m%n
rootLogger.level = INFO
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = Console