t.me/atinfo_chat Telegram группа по автоматизации тестирования

При запуске через Maven создоваемый тестом файл отличается от ожидаемого, а при запуске того же теста черз IDE, соотвествует ожидаемому(решено).

rest-assured
testng
maven
Теги: #<Tag:0x00007f21d2287968> #<Tag:0x00007f21d2287800> #<Tag:0x00007f21d22876c0>

(Сергей) #1

Здравствуйте коллеги и все не равнодушные, помогите понять, что я делаю не так. Есть проект по api тестированию (Maven+Rest Assured+TestNg). Тесты делаю следующее:

  1. Тест MODS_startExport_Test() инициирует задачу экспорта сохраняя id этой задачи и вид экспорта в объект;

  2. Тест MODS_checkExport_Test() считывает id задачи и проверяет выполнена ли она;

  3. Тест MODS_compareExportResult_Test(), если задача экспорта была выполнена успешно, запрашивает результат экспорта, сохраняет его в файл и сравнивает этот файл с эталонным файлом.

Проблема заключается в том, что при запуске из Eclipse все прекрасно работает, а вот при выполнении через Maven, 3-й тест создает файл с совсем другим содержанием и тест соответственно падает. Почему так происходит?

Тесты:

Сводка
public class RestAssured_Export extends Setup {
	
	// Create a new instance of DataClasses 
	DataClasses data = new DataClasses();
	
	// Create a new ExportDATA object to store export process information
	ExportDATA ExportTask = data.new ExportDATA(0, null, null);

@Test()
	public void MODS_startExport_Test() {								
		Response response =  
		given().
		            log().
		 	    all().		       
			    pathParam("query", "gene").
			    pathParam("apikey", "apikey1").		 
		when(). 
		    	get("/export/mods?query={query}&apikey={apikey}").		    		    
		then().
			   log().
			   headers().		 
		assertThat().
		   	   statusCode(202).extract().response();
		
		// Get the export task id from the 'location' string in response headers and assign it to an int variable 
		int exportID = Integer.parseInt((response.header("location")).replaceAll("[^\\D]*[\\D+]", ""));			
		
		System.out.println("The Export task ID is "+exportID+"");
		// save test id and an export format to the exportTask object
		ExportTask.setTaskID(exportID);	
		ExportTask.setExportFormat("MODS");
	}
	
	@Test(dependsOnMethods = "MODS_startExport_Test")
	public void MODS_checkExport_Test() throws Exception {		
			
		String status = "";
		
		while(!status.equals("COMPLETED")) {
						
			status =
			given().
			 		log().
			 		all().		       
				    pathParam("taskID", ExportTask.getTaskID()).								   
				    pathParam("apikey", "apikey1").		 
			when(). 
			    	get("/export/task/{taskID}?&apikey={apikey}").		    	   
			then().
				   log().
				   body().		 
			assertThat().
			   	   statusCode(200).
			   	   extract().path("state").toString();
	   	   
			System.out.println(status);
			
			if (status.equals("FAILED")) {
				ExportTask.setExportState("FAILED");
				throw new Exception("The Export task with ID "+ExportTask.getTaskID()+" has failed!"); 
			}	   	 
		}
		// save export state as 'completed' to the exportTask object
		ExportTask.setExportState("COMPLETED");
	}
			
	@Test(dependsOnMethods = "MODS_checkExport_Test")
	public void MODS_compareExportResult_Test() throws IOException {
		
		if (!ExportTask.getExportState().equals("COMPLETED") 
				&& !ExportTask.getExportFormat().equals("MODS")) {
			throw new SkipException("The MODS_compareExportResult_Test is skipped because the export with ID "
					+ ""+ExportTask.getTaskID()+" has been failed or was not a RIS export.");
		}
				
		File expectedMODSFile = new File("./src/test/resources/export/expectedMODS.mods");
		// create a new empty file
		File outputMODSFile = new File("./src/test/resources/export/references.mods");
		// save response as a byte array  
		byte[] exportFile =  
				
				given().
				 	    log().
				 	    all().		       
					    pathParam("taskID", ExportTask.getTaskID()).
					    pathParam("apikey", "apikey1").		 
				when(). 
				    	get("/export/task/{taskID}/result?&apikey={apikey}").
				    	asByteArray();
		
		// write the response to the file 
		OutputStream outStream = new FileOutputStream(outputMODSFile);
		outStream.write(exportFile);
		outStream.close();
			
		// check that the reference.ris exists 
		Assert.assertTrue(outputMODSFile.exists());
		
		// compare both files for equality  
		assertThat(expectedMODSFile, isIdenticalTo(outputMODSFile));
	}
}

Setup класс (наследуется классом RestAssured_Export):

Сводка
import org.testng.annotations.BeforeClass;

import io.restassured.RestAssured;
import io.restassured.config.EncoderConfig;

public class Setup {
	
	@BeforeClass
	public void setup() {
	    
		RestAssured.baseURI = "http://somesite.com";
		//RestAssured.baseURI = System.getProperty("hostName");
	    
	    RestAssured.basePath = "/api/";
	    //RestAssured.port = 8080;
	    RestAssured.config = RestAssured.config().encoderConfig(EncoderConfig.encoderConfig().defaultContentCharset("UTF-8"));
	}
}

ExportDATA класс (используется для хранения данных задачи):

Сводка
public class DataClasses {

	public class ExportDATA {
		
		int taskID;
		String exportState;
		String exportFormat;

		// constructor
		ExportDATA(int taskID, String exportState, String exportFormat) {
			this.taskID = taskID;
			this.exportState = exportState;
			this.exportFormat = exportFormat;
		}
		public int getTaskID() {
			return this.taskID;
		}
		public String getExportState() {
			return this.exportState;
		}
		public String getExportFormat() {
			return this.exportFormat;
		}
		public void setTaskID(int value) {
			this.taskID = value;
		}
		public void setExportState(String value) {
			this.exportState = value;
		}
		public void setExportFormat(String value) {
			this.exportFormat = value;
		}
	}
}

POM файл проекта:

Сводка
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://maven.apache.org/POM/4.0.0"
	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>sirius-api</groupId>
  <artifactId>sirius-api</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>
  <name>sirius-api</name>
  <!--  url>http://maven.apache.org</url-->

  <properties>
  	<project.java.version>1.8</project.java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <hostName>URL</hostName>
  </properties>

	<dependencies>

		<!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
		<dependency>
		    <groupId>io.rest-assured</groupId>
		    <artifactId>rest-assured</artifactId>
		    <version>4.0.0</version>
		</dependency>
		
		<dependency>
		      <groupId>io.rest-assured</groupId>
		      <artifactId>json-path</artifactId>
		      <version>4.0.0</version>
		</dependency>
		
		<dependency>
      		  <groupId>io.rest-assured</groupId>
      		  <artifactId>xml-path</artifactId>
      		  <version>4.0.0</version>
		</dependency>

		<dependency>
		    <groupId>io.rest-assured</groupId>
		    <artifactId>json-schema-validator</artifactId>
		    <version>4.0.0</version>
		</dependency>
		
		<dependency>
			<groupId>uk.co.datumedge</groupId>
			<artifactId>hamcrest-json</artifactId>
			<version>0.1</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.hamcrest/java-hamcrest -->
		<dependency>
		    <groupId>org.hamcrest</groupId>
		    <artifactId>java-hamcrest</artifactId>
		    <version>2.0.0.0</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest-all -->
		<dependency>
		    <groupId>org.hamcrest</groupId>
		    <artifactId>hamcrest-all</artifactId>
		    <version>1.3</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
		<dependency>
		    <groupId>commons-io</groupId>
		    <artifactId>commons-io</artifactId>
		    <version>2.6</version>
		</dependency>
	
		<dependency>
		    <groupId>org.xmlunit</groupId>
		    <artifactId>xmlunit-matchers</artifactId>
		    <version>2.6.2</version>
		</dependency>

		<dependency>
			<groupId>org.xmlunit</groupId>
			<artifactId>xmlunit-core</artifactId>
			<version>2.6.2</version>
		</dependency>
		
		<dependency>
			<groupId>org.testng</groupId>
			<artifactId>testng</artifactId>
			<version>6.14.3</version>
		</dependency>			
	
</dependencies>
	
		<build>		
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.20</version>
				<configuration>
				    <reportsDirectory>./test-output</reportsDirectory>
					<testFailureIgnore>true</testFailureIgnore>
					<suiteXmlFiles>
						<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
					</suiteXmlFiles>
					<!-- property>
							<name>usedefaultlisteners</name>
							<value>true</value>
					</property-->
				</configuration>
			</plugin>
		</plugins>
				
		
	</build>	
</project>

(Сергей Кузьмин) #2

пожалуйста покажите эти файл с совсем разным содержанием - надеюсь там нет военной тайны


(Сергей) #3

Тайна есть, но не военная :slight_smile: Вот файл, который получается через Maven: reference.mods, а вот то, что должно быть: expectedMods.mods

Похоже дело в кодировке, т.е. почему-то Maven использует не UTF-8, но это не точно


(Сергей Кузьмин) #4

емнип надо encoding передавать в энвайронмент - я не эксперт - вставте примены напрямую между прочем
ВАШ REFERENCE.mods это эксел а другой это XML

Elsevier Text Mining Basic Search Results, retrieved by Dev Team on 2019-08-12
[Query]: cancer
[Search Index]: Text Mining Standard Index

(Сергей) #5

На самом деле дело было не в encoding, и это хорошо что вы заметили что файлы отличаются по формату :slight_smile: Тут я привел пример только трех тестов на один тип экспорта, а их много больше и оказалось что Maven исполняет их в другом порядке чем Eclips, в результате получается что тест, который создает и сравнивает файлы, использует taskID от другого экспорта, отсюда и разные файлы на выходе.

Я пробовал использовать аннотацию порядка исполнения: @Test(priority=n) но в таком случае Maven вообще игнорит тесты где создаются файлы.

В общем я решил проблему путем передачи taskID как уникальной переменной для каждого типа экспорта, и чтобы не создавать кучу геттеров и сеттеров, использовал ITestContent:

Сводка
	@Test
	public void RIS_startExport_Test(ITestContext exportData) {						
		Response response =  
		given().
		 		log().
		 		all().		       
			    pathParam("query", "cancer").
			    pathParam("apikey", "apikey1").		 
		when(). 
		    	get("/export/ris?query={query}&apikey={apikey}").		    		    
		then().
			   log().
			   headers().		 
		assertThat().
		   	   statusCode(202).extract().response();
		// Get the export task id from the 'location' string in response headers and assign it to an int variable 
		int exportID = Integer.parseInt((response.header("location")).replaceAll("[^\\D]*[\\D+]", ""));			
		
		System.out.println("The Export task ID is "+exportID+"");
		// save test id to the exportTask object
		//ExportTask.setTaskID(exportID);
		exportData.setAttribute("taskID_RIS", exportID);
		// save RIS format to the exportTask object
		//ExportTask.setExportFormat("RIS");
		exportData.setAttribute("exportFormat", "RIS");
	}
	
	@Test(dependsOnMethods = "RIS_startExport_Test")
	public void RIS_checkExport_Test(ITestContext exportData) throws Exception {		
			
		String status = "";
		
		while(!status.equals("COMPLETED")) {
						
			status =
			given().
			 		log().
			 		all().		       
				    pathParam("taskID", exportData.getAttribute("taskID_RIS")).
				    pathParam("apikey", "apikey1").		 
			when(). 
			    	get("/export/task/{taskID}?&apikey={apikey}").		    	   
			then().
				   log().
				   body().		 
			assertThat().
				   //contentType(ContentType.JSON).
			   	   statusCode(200).
			   	   extract().path("state").toString();
	   	   
			System.out.println(status);
			
			if (status.equals("FAILED")) {
				//ExportTask.setExportState("FAILED");
				exportData.setAttribute("exportState_RIS", "FAILED");
				throw new Exception("The Export task with ID "+exportData.getAttribute("taskID_RIS")+" has failed!"); 
			}	   	 
		}
		// save export state as 'completed' to the exportTask object
		exportData.setAttribute("exportState_RIS", "COMPLETED");
		//ExportTask.setExportState("COMPLETED");
	}

@Test(dependsOnMethods = "RIS_checkExport_Test")
	public void RIS_compareExportResult_Test(ITestContext exportData) throws IOException {
		
		if (!exportData.getAttribute("exportState_RIS").equals("COMPLETED") 
				&& !exportData.getAttribute("exportFormat").equals("RIS")) {
			throw new SkipException("The RIS_compareExportResult_Test is skipped because the export with ID "
					+ ""+exportData.getAttribute("taskID_RIS")+" has been failed or was not a RIS export.");
		}			
		File expectedRISFile = new File("./src/test/resources/export/expectedRIS.ris");
		// create a new empty file
		File outputRISFile = new File("./src/test/resources/export/reference.ris");
		// save response as a byte array  
		byte[] exportFile =  
				
				given().
				 	    log().
				 	    all().		       
					    pathParam("taskID", exportData.getAttribute("taskID_RIS")).				
					    pathParam("apikey", "apikey1").		 
				when(). 
				    	get("/export/task/{taskID}/result?&apikey={apikey}").
				    	asByteArray();
		
		// write the response to the file 
		OutputStream outStream = new FileOutputStream(outputRISFile);
		outStream.write(exportFile);
		outStream.close();
			
		// check that the reference.ris exists 
		Assert.assertTrue(outputRISFile.exists());
		// compare the reference.ris (from response) and the expectedRIS (the reference RIS export file) for equality 
		Assert.assertTrue(FileUtils.contentEquals(outputRISFile, expectedRISFile));
	}

Почему Maven исполняет тесты в другом порядке чем Eclips, я так и не понял, надеюсь кому-нибудь все это пригодится.


(Сергей Кузьмин) #6

спасибо за анализ – упорядочение тестов это отдельный хорошо известный “can ot worms”