Compare commits
No commits in common. "main" and "api-master" have entirely different histories.
main
...
api-master
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# Project exclude paths
|
||||
/target/
|
||||
/.idea/
|
||||
*.iml
|
||||
4
helpdesk-api-test-main/.gitignore
vendored
Normal file
4
helpdesk-api-test-main/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# Project exclude paths
|
||||
/target/
|
||||
/.idea/
|
||||
*.iml
|
||||
42
helpdesk-api-test-main/pom.xml
Normal file
42
helpdesk-api-test-main/pom.xml
Normal file
@ -0,0 +1,42 @@
|
||||
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>helpdesk-api-test</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<version>4.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<version>6.9.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,5 @@
|
||||
package model;
|
||||
|
||||
public class AuthToken {
|
||||
// todo: serialized поля, согласно swagger, а также геттеры и сеттеры
|
||||
}
|
||||
18
helpdesk-api-test-main/src/main/java/model/Status.java
Normal file
18
helpdesk-api-test-main/src/main/java/model/Status.java
Normal file
@ -0,0 +1,18 @@
|
||||
package model;
|
||||
|
||||
/** Статусы тикета, используемые в тестах */
|
||||
public enum Status {
|
||||
OPEN(1),
|
||||
CLOSED(4),
|
||||
;
|
||||
|
||||
private final int code;
|
||||
|
||||
Status(int code) {
|
||||
this.code=code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
19
helpdesk-api-test-main/src/main/java/model/Ticket.java
Normal file
19
helpdesk-api-test-main/src/main/java/model/Ticket.java
Normal file
@ -0,0 +1,19 @@
|
||||
package model;
|
||||
|
||||
/** Объект тикета (POJO) */
|
||||
public class Ticket {
|
||||
|
||||
// todo: serialized поля, геттеры и сеттеры
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
// todo
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// todo
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
40
helpdesk-api-test-main/src/test/java/api/BaseTest.java
Normal file
40
helpdesk-api-test-main/src/test/java/api/BaseTest.java
Normal file
@ -0,0 +1,40 @@
|
||||
package api;
|
||||
|
||||
import model.AuthToken;
|
||||
import model.Status;
|
||||
import model.Ticket;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
|
||||
/** Абстрактный класс, содержащий общие для всех тестов методы */
|
||||
public abstract class BaseTest {
|
||||
@BeforeClass
|
||||
public void prepare() {
|
||||
// todo: загрузить в системные переменные "base.uri" из "config.properties"
|
||||
|
||||
String baseUri = System.getProperty("base.uri");
|
||||
if (baseUri == null || baseUri.isEmpty()) {
|
||||
throw new RuntimeException("В файле \"config.properties\" отсутствует значение \"base.uri\"");
|
||||
}
|
||||
|
||||
// todo: подготовить глобальные преднастройки для запросов
|
||||
}
|
||||
|
||||
protected AuthToken login() {
|
||||
// todo: отправить запрос на получения токена, используя учетные данные из "config.properties"
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Ticket buildNewTicket(Status status, int priority) {
|
||||
// todo: создать объект с тестовыми данными
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Ticket createTicket(Ticket ticket) {
|
||||
// todo: отправить HTTP запрос для создания тикета
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package api;
|
||||
|
||||
import model.Ticket;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/** Создание и проверка тикета */
|
||||
public class CreateTicketTest extends BaseTest {
|
||||
|
||||
@Test
|
||||
public void createTicketTest() {
|
||||
// todo: создать тикет и проверить, что он находится в системе
|
||||
}
|
||||
|
||||
protected Ticket getTicket(int id) {
|
||||
// todo: отправить HTTP запрос на получение тикета по его id
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package api;
|
||||
|
||||
import model.Ticket;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/** Обновление тикета */
|
||||
public class UpdateTicketTest extends BaseTest {
|
||||
|
||||
@Test
|
||||
public void updateTicketTest() {
|
||||
// todo: создать тикет со статусом Closed, затем обновить тикет и проверить сообщение об ошибке (негативный сценарий)
|
||||
}
|
||||
|
||||
private void updateTicketNegative(Ticket ticket) {
|
||||
// todo: отправить HTTP запрос для обновления данных тикета и сразу же проверить статус код (должен соответствовать ошибке)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
# Параметры конфигурации в формате:
|
||||
# key=value
|
||||
47
pom.xml
Normal file
47
pom.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>helpdesk-api-test</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>2.22</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<version>4.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<version>6.9.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
23
src/main/java/model/AuthToken.java
Normal file
23
src/main/java/model/AuthToken.java
Normal file
@ -0,0 +1,23 @@
|
||||
package model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class AuthToken {
|
||||
@SerializedName("username")
|
||||
private String username;
|
||||
|
||||
@SerializedName("password")
|
||||
private String password;
|
||||
|
||||
@SerializedName("token")
|
||||
private String token;
|
||||
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
public String getUsername() { return username; }
|
||||
|
||||
public void setPassword(String password) { this.password = password; }
|
||||
public String getPassword() { return password; }
|
||||
|
||||
public void setToken(String token) { this.token = token; }
|
||||
public String getToken() { return token; }
|
||||
}
|
||||
18
src/main/java/model/Status.java
Normal file
18
src/main/java/model/Status.java
Normal file
@ -0,0 +1,18 @@
|
||||
package model;
|
||||
|
||||
/** Статусы тикета, используемые в тестах */
|
||||
public enum Status {
|
||||
OPEN(1),
|
||||
CLOSED(4),
|
||||
;
|
||||
|
||||
private final int code;
|
||||
|
||||
Status(int code) {
|
||||
this.code=code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
146
src/main/java/model/Ticket.java
Normal file
146
src/main/java/model/Ticket.java
Normal file
@ -0,0 +1,146 @@
|
||||
package model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/** Объект тикета (POJO) */
|
||||
public class Ticket {
|
||||
|
||||
@SerializedName("id")
|
||||
private Integer id;
|
||||
|
||||
@JsonIgnore
|
||||
@SerializedName("due_date")
|
||||
private String due_date;
|
||||
|
||||
@SerializedName("assigned_to")
|
||||
private String assigned_to;
|
||||
|
||||
@SerializedName("title")
|
||||
private String title;
|
||||
|
||||
@JsonIgnore
|
||||
@SerializedName("created")
|
||||
private String created;
|
||||
|
||||
@JsonIgnore
|
||||
@SerializedName("modified")
|
||||
private String modified;
|
||||
|
||||
@SerializedName("submitter_email")
|
||||
private String submitter_email;
|
||||
|
||||
@SerializedName("status")
|
||||
private Integer status;
|
||||
|
||||
@SerializedName("on_hold")
|
||||
private Boolean on_hold;
|
||||
|
||||
@SerializedName("description")
|
||||
private String description;
|
||||
|
||||
@SerializedName("resolution")
|
||||
private String resolution;
|
||||
|
||||
@SerializedName("priority")
|
||||
private Integer priority;
|
||||
|
||||
@SerializedName("last_escalation")
|
||||
private String last_escalation;
|
||||
|
||||
@SerializedName("secret_key")
|
||||
private String secret_key;
|
||||
|
||||
@SerializedName("queue")
|
||||
private Integer queue;
|
||||
|
||||
@SerializedName("kbitem")
|
||||
private Integer kbitem;
|
||||
|
||||
@SerializedName("merged_to")
|
||||
private Integer merged_to;
|
||||
|
||||
public void setId(Integer id) { this.id = id; }
|
||||
public Integer getId() { return id; }
|
||||
|
||||
public void setDue_date(String due_date) { this.due_date = due_date; }
|
||||
public String getDue_date() { return due_date; }
|
||||
|
||||
public void setAssigned_to(String assigned_to) { this.assigned_to = assigned_to; }
|
||||
public String getAssigned_to() { return assigned_to; }
|
||||
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public String getTitle() { return title; }
|
||||
|
||||
public void setCreated(String created) { this.created = created; }
|
||||
public String getCreated() { return created; }
|
||||
|
||||
public void setModified(String modified) { this.modified = modified; }
|
||||
public String getModified() { return modified; }
|
||||
|
||||
public void setSubmitter_email(String submitter_email) { this.submitter_email = submitter_email; }
|
||||
public String getSubmitter_email() { return submitter_email; }
|
||||
|
||||
public void setStatus(Integer status) { this.status = status; }
|
||||
public Integer getStatus() { return status; }
|
||||
|
||||
public void setOn_hold(boolean on_hold) { this.on_hold = on_hold; }
|
||||
public boolean isOn_hold() { return on_hold; }
|
||||
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
public String getDescription() { return description; }
|
||||
|
||||
public void setResolution(String resolution) { this.resolution = resolution; }
|
||||
public String getResolution() { return resolution; }
|
||||
|
||||
public void setPriority(Integer priority) { this.priority = priority; }
|
||||
public Integer getPriority() { return priority; }
|
||||
|
||||
public void setLast_escalation(String last_escalation) { this.last_escalation = last_escalation; }
|
||||
public String getLast_escalation() { return last_escalation; }
|
||||
|
||||
public void setSecret_key(String secret_key) { this.secret_key = secret_key; }
|
||||
public String getSecret_key() { return secret_key; }
|
||||
|
||||
public void setQueue(Integer queue) { this.queue = queue; }
|
||||
public Integer getQueue() { return queue; }
|
||||
|
||||
public void setKbitem(Integer kbitem) { this.kbitem = kbitem; }
|
||||
public Integer getKbitem() { return kbitem; }
|
||||
|
||||
public void setMerged_to(Integer merged_to) { this.merged_to = merged_to; }
|
||||
public Integer getMerged_to() { return merged_to; }
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (getClass() != o.getClass()) return false;
|
||||
|
||||
Ticket other = (Ticket) o;
|
||||
|
||||
return Objects.equals(due_date, other.due_date) &&
|
||||
Objects.equals(assigned_to, other.assigned_to) &&
|
||||
Objects.equals(title, other.title) &&
|
||||
Objects.equals(submitter_email, other.submitter_email) &&
|
||||
Objects.equals(status, other.status) &&
|
||||
Objects.equals(on_hold, other.on_hold) &&
|
||||
Objects.equals(description, other.description) &&
|
||||
Objects.equals(resolution, other.resolution) &&
|
||||
Objects.equals(priority, other.priority) &&
|
||||
Objects.equals(last_escalation, other.last_escalation) &&
|
||||
Objects.equals(secret_key, other.secret_key) &&
|
||||
Objects.equals(queue, other.queue) &&
|
||||
Objects.equals(kbitem, other.kbitem) &&
|
||||
Objects.equals(merged_to, other.merged_to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(due_date, assigned_to, title,
|
||||
submitter_email, status, on_hold, description, resolution,
|
||||
priority, last_escalation, secret_key, queue, kbitem, merged_to);
|
||||
}
|
||||
}
|
||||
114
src/test/java/api/BaseTest.java
Normal file
114
src/test/java/api/BaseTest.java
Normal file
@ -0,0 +1,114 @@
|
||||
package api;
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.builder.RequestSpecBuilder;
|
||||
import io.restassured.filter.log.LogDetail;
|
||||
import io.restassured.filter.log.ResponseLoggingFilter;
|
||||
import io.restassured.http.ContentType;
|
||||
import model.AuthToken;
|
||||
import model.Status;
|
||||
import model.Ticket;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
|
||||
/** Абстрактный класс, содержащий общие для всех тестов методы */
|
||||
public abstract class BaseTest {
|
||||
@BeforeClass
|
||||
public void prepare() throws IOException{
|
||||
|
||||
System.getProperties().load(ClassLoader.getSystemResourceAsStream("config.properties"));
|
||||
|
||||
String baseUri = System.getProperty("base.uri");
|
||||
if (baseUri == null || baseUri.isEmpty()) {
|
||||
throw new RuntimeException("В файле \"config.properties\" отсутствует значение \"base.uri\"");
|
||||
}
|
||||
|
||||
RestAssured.requestSpecification = new RequestSpecBuilder()
|
||||
.setBaseUri(baseUri)
|
||||
.setAccept(ContentType.JSON)
|
||||
.setContentType(ContentType.JSON)
|
||||
.log(LogDetail.ALL)
|
||||
.build();
|
||||
|
||||
RestAssured.filters(new ResponseLoggingFilter());
|
||||
}
|
||||
|
||||
protected AuthToken login() {
|
||||
|
||||
String username = System.getProperty("username");
|
||||
if (username == null || username.isEmpty()) {
|
||||
throw new RuntimeException("В файле \"config.properties\" отсутствует значение \"username\"");
|
||||
}
|
||||
|
||||
String password = System.getProperty("password");
|
||||
if (password == null || password.isEmpty()) {
|
||||
throw new RuntimeException("В файле \"config.properties\" отсутствует значение \"password\"");
|
||||
}
|
||||
|
||||
AuthToken auth = new AuthToken();
|
||||
auth.setUsername(username);
|
||||
auth.setPassword(password);
|
||||
|
||||
|
||||
AuthToken actual =
|
||||
given()
|
||||
.body(auth)
|
||||
.when()
|
||||
.post("/api/login")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract().as(AuthToken.class);
|
||||
|
||||
auth.setToken(actual.getToken());
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
protected Ticket buildNewTicket(Status status, int priority) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
Random random = new Random();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
|
||||
|
||||
Ticket ticket = new Ticket();
|
||||
|
||||
String title = "Проверка rest-assured " + UUID.randomUUID();
|
||||
String secret_key = UUID.randomUUID().toString();
|
||||
boolean on_hold = random.nextBoolean();
|
||||
String due_date = now.format(formatter);
|
||||
int queue = 1;
|
||||
|
||||
//ticket.setDue_date(due_date);
|
||||
ticket.setAssigned_to("admin");
|
||||
ticket.setTitle(title);
|
||||
ticket.setStatus(status.getCode());
|
||||
ticket.setPriority(priority);
|
||||
ticket.setSecret_key(secret_key);
|
||||
ticket.setOn_hold(on_hold);
|
||||
ticket.setQueue(queue);
|
||||
|
||||
return ticket;
|
||||
}
|
||||
|
||||
protected Ticket createTicket(Ticket ticket) {
|
||||
AuthToken authToken = login();
|
||||
String token = authToken.getToken();
|
||||
|
||||
Ticket actual =
|
||||
given()
|
||||
.header("Authorization", "Token " + token)
|
||||
.body(ticket)
|
||||
.when()
|
||||
.post("/api/tickets")
|
||||
.then()
|
||||
.statusCode(201)
|
||||
.extract().as(Ticket.class);
|
||||
|
||||
return actual;
|
||||
}
|
||||
}
|
||||
53
src/test/java/api/CreateTicketTest.java
Normal file
53
src/test/java/api/CreateTicketTest.java
Normal file
@ -0,0 +1,53 @@
|
||||
package api;
|
||||
|
||||
import model.AuthToken;
|
||||
import model.Status;
|
||||
import model.Ticket;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
|
||||
|
||||
/** Создание и проверка тикета */
|
||||
public class CreateTicketTest extends BaseTest {
|
||||
// @Test
|
||||
// public void loginTest() {
|
||||
// AuthToken token = login();
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void ticketTest() {
|
||||
// Ticket ticket = buildNewTicket(Status.OPEN, 3);
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void createTicketTest() {
|
||||
Ticket ticket1 = createTicket(buildNewTicket(Status.OPEN, 3));
|
||||
int id = ticket1.getId();
|
||||
Ticket ticket2 = getTicket(id);
|
||||
Assert.assertEquals(ticket1, ticket2);
|
||||
}
|
||||
|
||||
protected Ticket getTicket(int id) {
|
||||
AuthToken authToken = login();
|
||||
String token = authToken.getToken();
|
||||
|
||||
Ticket actual =
|
||||
given()
|
||||
.header("Authorization", "Token " + token)
|
||||
.pathParam("ticketId", id)
|
||||
.when()
|
||||
.get("api/tickets/{ticketId}")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract().as(Ticket.class);
|
||||
|
||||
return actual;
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void getTicketTest(){
|
||||
// getTicket(1);
|
||||
// }
|
||||
}
|
||||
34
src/test/java/api/UpdateTicketTest.java
Normal file
34
src/test/java/api/UpdateTicketTest.java
Normal file
@ -0,0 +1,34 @@
|
||||
package api;
|
||||
|
||||
import model.AuthToken;
|
||||
import model.Status;
|
||||
import model.Ticket;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
|
||||
/** Обновление тикета */
|
||||
public class UpdateTicketTest extends BaseTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void updateTicketTest() {
|
||||
Ticket ticket = buildNewTicket(Status.CLOSED, 1);
|
||||
Ticket posted = createTicket(ticket);
|
||||
updateTicketNegative(posted);
|
||||
|
||||
}
|
||||
|
||||
private void updateTicketNegative(Ticket ticket) {
|
||||
AuthToken authToken = login();
|
||||
|
||||
given()
|
||||
.header("Authorization", "Token " + authToken.getToken())
|
||||
.pathParam("ticketId", ticket.getId())
|
||||
.body(ticket)
|
||||
.when()
|
||||
.put("/api/tickets/{ticketId}")
|
||||
.then()
|
||||
.statusCode(422);
|
||||
}
|
||||
}
|
||||
5
src/test/resources/config.properties
Normal file
5
src/test/resources/config.properties
Normal file
@ -0,0 +1,5 @@
|
||||
base.uri=https://at-sandbox.workbench.lanit.ru/
|
||||
token=ad9e96f7199e808dffc307832da5c3ee0a7351a2
|
||||
|
||||
username=admin
|
||||
password=adminat
|
||||
Loading…
Reference in New Issue
Block a user