「雙花」BUG的測試分享

「雙花」一詞我是從區塊鏈領域的聽到的,查了一下資料,基本全部的引用都是基於區塊鏈,可是今天所講的「雙花」不是區塊鏈領域,而是普通的接口測試中遇到的BUG,因爲概念一致,因此採用「雙花」一詞。 雙花,顧名思義,花了兩次,一分錢或者交換流通的物品。下面分享一下本身在工做中遇到的一個雙花的BUG的測試方案和緣由解釋。java

場景:有一個兌換活動,大概金幣兌換禮物,金幣是整個平臺流通的貨幣,禮物價格不等。用戶登陸活動頁後,選擇不一樣的禮物輸入數量,點擊兌換。 接口:活動接口兩個:1、獲取活動詳情以及禮物詳情;2、兌換必定數量禮物。兌換記錄和消費記錄以及我的物品都是老接口,再也不贅述。 測試工具:Java(不惟一),把接口提供的功能封裝爲方法,而後經過多線程調用封裝號的方法,完成多線程請求兌換接口。apache

解決方案: 在常規測試場景之外,利用多線程併發去測試雙花BUG。主要利用了寫好的性能測試框架去併發去發送某一個httprequestbase對象,經過構造對應的測試數據,檢查測試完成後的測試數據,對比發現是否存在雙花的BUG。 用戶A,設置用戶餘額100,000,兌換價值100的禮物,併發1,010次。最終結果,用戶餘額爲零,兌換的1,000個改禮物,各類記錄正常。最後10次響應結果爲用戶餘額不足。編程

在兌換接口中,業務邏輯以下:獲取用戶餘額,判斷是否足以支付禮品總價,(大於等於時),發起扣幣以及記錄相關封裝模塊功能。json

BUG描述:在完成測試時,用戶獲取到的禮物數量大於1000,餘額爲零。最後10次請求,有一些是響應成功的。安全

BUG覆盤,在獲取完用戶餘額和判斷完總價以後,發起扣費等業務時,並無從新校驗用戶餘額(或者說改過程是非原子操做不安全),這樣致使了最後扣費的時候,使用的用戶餘額是舊的數值,其餘線程也還沒有完成扣費,形成了用戶的一份金幣,被當作兩份金幣消費了,也就是雙花。多線程

下面是測試代碼,主要用到了本身寫的測試框架,把HttpRequestBase對象組裝好以後丟到trhead對象裏面,設置請求次數和線程數。併發

package com.fission.najm.activity.before.workPractise;

import com.fission.najm.base.NajmBase;
import com.fun.frame.excute.Concurrent;
import com.fun.frame.thead.RequestThread;
import net.sf.json.JSONObject;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;

public class Exchange extends NajmBase {
	public String loginKey;
	public String exchangeCode = "";
	public int balance;
	public int coin;
	public HttpRequestBase Rechargerequest;
	public HttpRequestBase exchangeRequest;


	public static void main(String[] args) {
		NajmBase base = new NajmBase();
		Exchange exchange = new Exchange(base);
		exchange.recharge();
		RequestThread requestThread = new RequestThread(exchangeRequest, 101);
		new Concurrent(requestThread,10).start();
		allOver();
	}

	/**
	 * 充值
	 *
	 * @return
	 */
	public JSONObject recharge() {
		JSONObject response = null;
		String url = "http://www.7najm.com/cash/exchangecrecharge";
		JSONObject params = new JSONObject();
		params.put("loginKey", loginKey);
		params.put("exchangeCode", exchangeCode);
		params.put("requestType", "We");
		Rechargerequest = getHttpPost(url, params);
		//response = getHttpResponseEntityByJson(Rechargerequest);
		//output(response);
		return response;
	}

	/**
	 * 獲取充值記錄
	 *
	 * @return
	 */
	public JSONObject getRechargeRecord() {
		JSONObject response = null;
		String url = "http://www.7najm.com/cash/getecrrecord";
		JSONObject args = new JSONObject();
		args.put("loginKey", loginKey);
		args.put("page", 1);
		args.put("pageSize", 10);
		args.put("requestType", "Web");
		HttpGet httpGet = getHttpGet(url, args);
		response = getHttpResponseEntityByJson(httpGet);
		output(response);
		return response;
	}

	/**
	 * 獲取渠道商餘額
	 *
	 * @return
	 */
	public JSONObject getBalance() {
		JSONObject response = null;
		String url = "http://www.7najm.com/cash/exchangebalance";
		JSONObject args = new JSONObject();
		args.put("loginKey", loginKey);
		args.put("requestType", "Web");
		HttpGet httpGet = getHttpGet(url, args);
		response = getHttpResponseEntityByJson(httpGet);
		if (response.containsKey("dataInfo"))
			balance = response.getInt("dataInfo");
		output(response);
		return response;
	}

	/**
	 * 獲取充值碼
	 *
	 * @return
	 */
	public JSONObject getRechargeCode() {
		JSONObject response = null;
		String url = "http://www.7najm.com/cash/getexchangecode";
		JSONObject params = new JSONObject();
		params.put("loginKey", loginKey);
		params.put("requestType", "0");
		params.put("balance", coin);
		exchangeRequest = getHttpPost(url, params);
		response = getHttpResponseEntityByJson(exchangeRequest);
		if (response.containsKey("dataInfo")) {
			exchangeCode = response.getJSONObject("dataInfo").getString("exchangeCode");
		}
		output(response);
		return response;
	}

	/**
	 * 獲取充值碼列表
	 *
	 * @return
	 */
	public JSONObject getCodeRecord() {
		JSONObject response = null;
		String url = "http://www.7najm.com/cash/getecrecord";
		JSONObject args = new JSONObject();
		args.put("loginKey", loginKey);
		args.put("page", 1);
		args.put("pageSize", 20);
		args.put("requestType", "Web");
		args.put("codeType", 1);
		HttpGet httpGet = getHttpGet(url, args);
		response = getHttpResponseEntityByJson(httpGet);
		output(response);
		return response;
	}
}

往期文章精選

  1. java一行代碼打印心形
  2. Linux性能監控軟件netdata中文漢化版
  3. 接口測試代碼覆蓋率(jacoco)方案分享
  4. 性能測試框架
  5. 如何在Linux命令行界面愉快進行性能測試
  6. 圖解HTTP腦圖
  7. 寫給全部人的編程思惟
  8. 測試之JVM命令腦圖
  9. 將json數據格式化輸出到控制檯
  10. 如何測試機率型業務接口
  11. 「雙花」BUG的測試分享

公衆號地圖 ☢️ 一塊兒來~FunTester

相關文章
相關標籤/搜索