![jmeter响应断言](https://i-blog.csdnimg.cn/blog_migrate/09f2c3d91dca504aa0a0abd5b686af79.png)
jmeter响应断言
什么是清洁测试?
清洁代码规则同样适用于生产代码和测试代码。 每次都进行代码清理,包括编写测试时。 在添加新测试之后甚至在编写新测试之前,您通常会发现重构的机会。 当新测试需要其他测试中已经包含的部件(例如断言或系统配置)时,就会是这种情况。
此类调整应考虑到《清洁法规》的基本原则。 它们主要涉及保持可读性和保持引入进一步更改的便利性。 我们还应该确保代码能够快速阅读和理解。
重构示例
以下是一些集成测试的集合。 他们检查访问健身俱乐部(健身房,桑拿浴室,游泳池)的价格表。 该逻辑还包括忠诚度积分的计算。
尽管此测试的示例很短,但它已经包含一些代码重复项。 在每个测试用例的开头和结尾都可以找到重复的代码。
@Test
public void twoHours_isOnly_payEntryFee() {
Facility beFitGym = new Facility( "Be Fit Gym" , Facility.GYM);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// when
client.addVisit(visit);
String payment = client.getReceipt();
// Then
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[1]" )
.isEqualTo( "Be Fit Gym" );
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[2]" )
.isEqualTo( "4.0" );
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[3]" )
.isEqualTo( "100" );
}
@Test
public void twoHours_PayForEach() {
// Given
Facility beFitGym = new Facility( "Jacuzzi" , Facility.STEAM_BATH);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// When
client.addVisit(visit);
String payment = client.getReceipt();
// Then
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[1]" )
.isEqualTo( "Be Fit Jacuzzi" );
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[2]" )
.isEqualTo( "10.0" );
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[3]" )
.isEqualTo( "300" );
}
一步一步重构
格式
在进行第一次转换之前,请注意代码格式化的价值。 上面的代码已经被格式化。 在此之前,它看起来像下面的代码。 当代码更清晰时,您可能会看到区别?
@Test
public void twoHours_PayForEach() {
...
assertThat(payment).valueByXPath( "/table/tr[1]/td[1]" ).isEqualTo( "Gym" );
assertThat(payment).valueByXPath( "/table/tr[1]/td[2]" ).isEqualTo( "10.0" );
assertThat(payment).valueByXPath( "/table/tr[1]/td[3]" ).isEqualTo( "300" );
}
使断言取决于局部变量
在格式良好的代码中,代码重复更为明显。 这就是我准备代码以提取包含逻辑重复的方法的方式。 在执行方法提取之前,我将通过提取重复代码使它们依赖于局部变量。
@Test
public void twoHours_payEntryFee() {
// Given
Facility beFitGym = new Facility( "Be Fit Gym" , Facility.GYM);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// When
client.addVisit(visit);
String payment = client.getReceipt();
// Then
String facilityName = "Be Fit Gym" ;
String facilityPrice = "4.0" ;
String facilityPoints = "100" ;
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[1]" )
.isEqualTo(facilityName);
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[2]" )
.isEqualTo(facilityPrice);
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[3]" )
.isEqualTo(facilityPoints);
}
提取断言方法
现在该提取方法了。 在大多数Java开发环境中,这是一种自动代码重构。
private void assertFacility(String payment,
String facilityName,
String facilityPrice,
String facilityPoints) {
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[1]" )
.isEqualTo(facilityName);
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[2]" )
.isEqualTo(facilityPrice);
assertThat(payment)
.valueByXPath( "/table/tr[1]/td[3]" )
.isEqualTo(facilityPoints);
}
不再需要提取的局部变量,因此我们可以内联它们。 以下是此测试重构的结果。
@Test
public void twoHours_isOnly_payEntryFee() {
Facility beFitGym = new Facility( "Be Fit Gym" , Facility.GYM);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// when
client.addVisit(visit);
String payment = client.getReceipt();
// Then
assertFacility(payment, "Be Fit Gym" , 4.0 , 100 );
}
@Test
public void twoHours_PayForEach() {
// Given
Facility beFitGym = new Facility( "Jacuzzi" , Facility.STEAM_BATH);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// When
client.addVisit(visit);
String payment = client.getReceipt();
// Then
assertFacility(payment, "Jacuzzi" , 10.0 , 150 );
}
注意方法的参数
请注意,测试变得更短了。 但是,现在的问题是另外属于两个组的参数的数量。 第一组是输入数据(第一个参数),第二组是每个断言的值(接下来的三个参数)。 此外,如果彼此相邻的参数属于同一类型,则很容易混淆其顺序。
创建一个新的断言类
接下来,我将使用以上两组参数作为后续更改的方向。 我将方法放在一个新类中,并将其中一个组定义为构造函数参数。 然后,当前方法将仅包含来自第二组的参数,并将通过类字段访问第一组。
Dokonaj ektrakcji klasy poprzezekstrakcjędelegata
为了创建一个新类,我启动了“提取委托”代码重构,这是IntelliJ IDE中Java语言的另一种自动转换。
这是代码转换的结果。
private final FacilityAssertion facilityAssertion = new FacilityAssertion();
@Test
public void twoHours_isOnly_payEntryFee() {
Facility beFitGym = new Facility( "Be Fit Gym" , Facility.GYM);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// when
client.addVisit(visit);
String payment = client.getReceipt();
// Then
facilityAssertion.assertFacility(payment, "Be Fit Gym" , 4.0 , 100 );
}
@Test
public void twoHours_PayForEach() {
// Given
Facility beFitGym = new Facility( "Jacuzzi" , Facility.STEAM_BATH);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// When
client.addVisit(visit);
String payment = client.getReceipt();
// Then
facilityAssertion.assertFacility(payment, "Jacuzzi" , 10.0 , 150 );
}
内联字段
课堂上多余的部分不是我的目标。 所以我正在吸收这个领域。 然后,无论逻辑在何处使用该字段,都会从头开始重新创建新的断言对象。
@Test
public void twoHours_isOnly_payEntryFee() {
Facility beFitGym = new Facility( "Be Fit Gym" , Facility.GYM);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// when
client.addVisit(visit);
String payment = client.getReceipt();
// Then
new FacilityAssetion().assertFacility(payment, "Be Fit Gym" , 4.0 , 100 );
}
@Test
public void twoHours_PayForEach() {
// Given
Facility beFitGym = new Facility( "Jacuzzi" , Facility.STEAM_BATH);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// When
client.addVisit(visit);
String payment = client.getReceipt();
// Then
new FacilityAssetion().assertFacility(payment, "Jacuzzi" , 10.0 , 150 );
}
然后,我重新提取“ assertFacility”方法。 由于这一点,调用断言构造器将只在一个地方。 低于重构结果。
private void assertFacility(String payment, String facilityName,
String facilityPrice, String facilityPoints) {
new FacilityAssertion()
.assertFacility(payment, facilityName,
facilityPrice, facilityPoints);
}
@Test
public void twoHours_isOnly_payEntryFee() {
Facility beFitGym = new Facility( "Be Fit Gym" , Facility.GYM);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// when
client.addVisit(visit);
String payment = client.getReceipt();
// Then
assertFacility(payment, "Be Fit Gym" , 4.0 , 100 );
}
@Test
public void twoHours_PayForEach() {
// Given
Facility beFitGym = new Facility( "Jacuzzi" , Facility.STEAM_BATH);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// When
client.addVisit(visit);
String payment = client.getReceipt();
// Then
assertFacility(payment, "Jacuzzi" , 10.0 , 150 );
}
将参数从方法移至构造函数
当前仅从一个位置调用构造函数(FacilityAssertion)。 因此,我在构造函数中添加了一个新参数,然后在此类中添加了一个字段。 当该方法使用“付款”字段而不是“付款”参数时–我可以删除不必要的参数。
用静态方法调用替换构造函数
接下来,在FacilityAssertion类中,我运行自动代码转换“用静态方法替换构造函数调用”。
public class FacilityAssertion {
private String payment;
private FacilityAssertion(String payment) {
this .payment = payment;
}
public static FacilityAssertion assertThat(String payment) {
return new FacilityAssertion(payment);
}
void hasAttributes(String facilityName, String facilityPrice,
String facilityPoints) {
XmlAssert.assertThat( this .payment)
.valueByXPath( "/table/tr[1]/td[1]" )
.isEqualTo(facilityName);
XmlAssert.assertThat( this .payment)
.valueByXPath( "/table/tr[1]/td[2]" )
.isEqualTo(facilityPrice);
XmlAssert.assertThat( this .payment)
.valueByXPath( "/table/tr[1]/td[3]" )
.isEqualTo(facilityPoints);
}
}
用方法链替换方法
是时候建立方法链了。 因此,我最后提取了一些新方法,这些方法将在其末尾包含“ return this”。 这将使我能够将这些方法的代码重构成一个调用链。
public class FacilityAssertion {
private String payment;
private FacilityAssertion(String payment) {
this .payment = payment;
}
public static FacilityAssertion assertThat(String payment) {
return new FacilityAssertion(payment);
}
FacilityAssertion hasAttributes(String facilityName,
String facilityPrice,
String facilityPoints) {
return hasName(facilityName)
.hasPrice(facilityPrice)
.hasPoints(facilityPoints);
}
FacilityAssertion hasPoints(String facilityPoints) {
XmlAssert.assertThat( this .payment)
.valueByXPath( "/table/tr[1]/td[3]" )
.isEqualTo(facilityPoints);
return this ;
}
FacilityAssertion hasPrice(String facilityPrice) {
XmlAssert.assertThat( this .payment)
.valueByXPath( "/table/tr[1]/td[2]" )
.isEqualTo(facilityPrice);
return this ;
}
FacilityAssertion hasName(String facilityName) {
XmlAssert.assertThat( this .payment)
.valueByXPath( "/table/tr[1]/td[1]" )
.isEqualTo(facilityName);
return this ;
}
}
内联初始断言方法
@Test
public void twoHours_isOnly_payEntryFee() {
Facility beFitGym = new Facility( "Be Fit Gym" , Facility.GYM);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// when
client.addVisit(visit);
String payment = client.getReceipt();
// Then
assertThat(payment)
.hasName( "Be Fit Gym" )
.hasPrice( "4.0" )
.hasPoints( "100" );
}
@Test
public void twoHours_PayForEach() {
// Given
Facility beFitGym = new Facility( "Jacuzzi" , Facility.STEAM_BATH);
Visit visit = new Visit(beFitGym, 2 );
Client client = new Client( "Mike" );
// When
client.addVisit(visit);
String payment = client.getReceipt();
// Then
assertThat(payment)
.hasName( "Jacuzzi" )
.hasPrice( "10.0" )
.hasPoints( "150" );
}
类似地使用构建器或工厂模式进行测试设置
您肯定已经注意到,现在测试配置仅在设施类型和访问持续时间上有所不同。 返回的设施名称始终相同,因此您可以单独检查一次,并且只能检查一次。
@Test
public void twoHours_isOnly_payEntryFee() {
// Given
String payment = newPaymentFor(Facility.GYM, 2 );
// Then
assertThat(payment)
.hasPrice( "4.0" )
.hasPoints( "100" );
}
@Test
public void twoHours_PayForEach() {
// Given
String payment = newPaymentFor(Facility.STEAM_BATH, 2 );
// Then
assertThat(payment)
.hasPrice( "10.0" )
.hasPoints( "150" );
}
如您所见,我们将上面的代码重构为干净的测试。 它们没有代码重复并且易于理解。 编写另一个测试也很简单。
图书馆促进流利的建设者模式
测试库支持流利的断言模式。 其中之一是asserjJ ,它与JUnit很好地兼容。 它遵循流畅的构建器模式,并允许一次创建一个断言。 它有助于在测试失败的情况下编写一条详细的消息,或者返回检查更多内容的新嵌套断言实例。
注意测试的可读性
鲍伯叔叔曾经说过(或写过):“像一流公民一样对待考试。” 因此,请通过不断重构来照顾您的测试! 清洁代码也是清洁测试!
请记住,重构金字塔的概念和SOLID原则同样适用于通过重构进行的清洁测试。
jmeter响应断言