国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

小談自動化測試:從ZStack Integration Test談起

EastWoodYang / 3443人閱讀

摘要:在這篇文章,筆者想談談對自動化測試的一些想法。很多人以為是用于做單元測試的。當然,這些測試都屬于集成測試。而單元測試以及如何在自己的應用中編寫一套更強大的自動測試框架這類主題,之后有機會筆者會再與大家分享。

本文首發于泊浮目的專欄:https://segmentfault.com/blog...
前言

筆者工作2年有余,剛開始實習的時候是不知道自動化測試這種神器的,在剛開始工作的時候往往苦于救火滅火再救火,搞的心力憔悴,一度懷疑猿生。實踐自動化測試后感覺生產力慢慢的解放了,那個時候搞的還是偏單機應用,測試的Cover也是止步在單機應用上。在接觸到了ZStack以后,由于其產品化的特性,對軟件質量要求偏高,然作為一個典型的分布式系統,測試的覆蓋率卻是較高的。在這篇文章,筆者想談談對自動化測試的一些想法。

收益

自動化測試的收益點很明顯,幾乎眾所周知:

保證軟件質量,重復的活交給機器來做,避免繁瑣重復的手動測試,節省人力;

為重構打下良好的基礎:軟件內部無論如何重構,對外部請求所返回的結果不應該有所變化;

保證核心類庫的邏輯不遭受破壞,同時也可以作為使用的“樣本”,由于沒有業務邏輯的耦合,代碼顯得更加清楚,便于閱讀;

.....

難點

既然收益這么高,為什么現實中自動化測試實施起來就像勞動人民愛勞動這句話一樣這么不現實呢?大概有這幾點:

對代碼架構要求較高:能靈活測試(集測、單測)的代碼往往是松耦合的,但是松耦合程度的控制可不是一個簡單的問題;

開發者得夠“懶”:開發者得愿意做一勞永逸的事,而不是每次都手測一下;

項目負責人對自動化測試不重視,眼里只有交付;

.....

ZStack的自動化測試實踐

ZStack的自動化測試是基于Junit使用Grovvy編寫的集成測試,在運行時會把依賴的Bean按需加載進來并啟動一個JVM進程,同時也會啟動一個基于Jetty的HTTPServer用于Mock Agent的行為。

很多人以為Junit是用于做單元測試的。其實并非如此,官網上的介紹是:JUnit is a simple framework to write repeatable tests. It is an instance of the xUnit architecture for unit testing frameworks.
從代碼說起
package org.zstack.test.integration.kvm.vm

import org.springframework.http.HttpEntity
import org.zstack.header.vm.VmCreationStrategy
import org.zstack.header.vm.VmInstanceState
import org.zstack.header.vm.VmInstanceVO
import org.zstack.kvm.KVMAgentCommands
import org.zstack.kvm.KVMConstant
import org.zstack.sdk.CreateVmInstanceAction
import org.zstack.sdk.DiskOfferingInventory
import org.zstack.sdk.ImageInventory
import org.zstack.sdk.InstanceOfferingInventory
import org.zstack.sdk.L3NetworkInventory
import org.zstack.sdk.VmInstanceInventory
import org.zstack.test.integration.kvm.Env
import org.zstack.test.integration.kvm.KvmTest
import org.zstack.testlib.EnvSpec
import org.zstack.testlib.SubCase
import org.zstack.testlib.VmSpec
import org.zstack.utils.gson.JSONObjectUtil

/**
 * Created by xing5 on 2017/2/22.
 */
class OneVmBasicLifeCycleCase extends SubCase {
    EnvSpec env

    def DOC = """
test a VM"s start/stop/reboot/destroy/recover operations 
"""

    @Override
    void setup() {
        useSpring(KvmTest.springSpec)
    }

    @Override
    void environment() {
        env = Env.oneVmBasicEnv()
    }

    @Override
    void test() {
        env.create {
            testStopVm()
            testStartVm()
            testRebootVm()
            testDestroyVm()
            testRecoverVm()
            testDeleteCreatedVm()
        }
    }

    void testRecoverVm() {
        VmSpec spec = env.specByName("vm")

        VmInstanceInventory inv = recoverVmInstance {
            uuid = spec.inventory.uuid
        }

        assert inv.state == VmInstanceState.Stopped.toString()

        // confirm the vm can start after being recovered
        testStartVm()
    }

    void testDestroyVm() {
        VmSpec spec = env.specByName("vm")

        KVMAgentCommands.DestroyVmCmd cmd = null

        env.afterSimulator(KVMConstant.KVM_DESTROY_VM_PATH) { rsp, HttpEntity e ->
            cmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.DestroyVmCmd.class)
            return rsp
        }

        destroyVmInstance {
            uuid = spec.inventory.uuid
        }

        assert cmd != null
        assert cmd.uuid == spec.inventory.uuid
        VmInstanceVO vmvo = dbFindByUuid(cmd.uuid, VmInstanceVO.class)
        assert vmvo.state == VmInstanceState.Destroyed
    }

    void testRebootVm() {
        // reboot = stop + start
        VmSpec spec = env.specByName("vm")

        KVMAgentCommands.StartVmCmd startCmd = null
        KVMAgentCommands.StopVmCmd stopCmd = null

        env.afterSimulator(KVMConstant.KVM_STOP_VM_PATH) { rsp, HttpEntity e ->
            stopCmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.StopVmCmd.class)
            return rsp
        }

        env.afterSimulator(KVMConstant.KVM_START_VM_PATH) { rsp, HttpEntity e ->
            startCmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.StartVmCmd.class)
            return rsp
        }

        VmInstanceInventory inv = rebootVmInstance {
            uuid = spec.inventory.uuid
        }

        assert startCmd != null
        assert startCmd.vmInstanceUuid == spec.inventory.uuid
        assert stopCmd != null
        assert stopCmd.uuid == spec.inventory.uuid
        assert inv.state == VmInstanceState.Running.toString()
    }

    void testStartVm() {
        VmSpec spec = env.specByName("vm")

        KVMAgentCommands.StartVmCmd cmd = null

        env.afterSimulator(KVMConstant.KVM_START_VM_PATH) { rsp, HttpEntity e ->
            cmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.StartVmCmd.class)
            return rsp
        }

        VmInstanceInventory inv = startVmInstance {
            uuid = spec.inventory.uuid
        }

        assert cmd != null
        assert cmd.vmInstanceUuid == spec.inventory.uuid
        assert inv.state == VmInstanceState.Running.toString()

        VmInstanceVO vmvo = dbFindByUuid(cmd.vmInstanceUuid, VmInstanceVO.class)
        assert vmvo.state == VmInstanceState.Running
        assert cmd.vmInternalId == vmvo.internalId
        assert cmd.vmName == vmvo.name
        assert cmd.memory == vmvo.memorySize
        assert cmd.cpuNum == vmvo.cpuNum
        //TODO: test socketNum, cpuOnSocket
        assert cmd.rootVolume.installPath == vmvo.rootVolume.installPath
        assert cmd.useVirtio
        vmvo.vmNics.each { nic ->
            KVMAgentCommands.NicTO to = cmd.nics.find { nic.mac == it.mac }
            assert to != null: "unable to find the nic[mac:${nic.mac}]"
            assert to.deviceId == nic.deviceId
            assert to.useVirtio
            assert to.nicInternalName == nic.internalName
        }
    }

    void testStopVm() {
        VmSpec spec = env.specByName("vm")

        KVMAgentCommands.StopVmCmd cmd = null

        env.afterSimulator(KVMConstant.KVM_STOP_VM_PATH) { rsp, HttpEntity e ->
            cmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.StopVmCmd.class)
            return rsp
        }

        VmInstanceInventory inv = stopVmInstance {
            uuid = spec.inventory.uuid
        }

        assert inv.state == VmInstanceState.Stopped.toString()

        assert cmd != null
        assert cmd.uuid == spec.inventory.uuid

        def vmvo = dbFindByUuid(cmd.uuid, VmInstanceVO.class)
        assert vmvo.state == VmInstanceState.Stopped
    }

    void testDeleteCreatedVm() {
        VmSpec spec = env.specByName("vm")
        DiskOfferingInventory diskOfferingInventory = env.inventoryByName("diskOffering")
        InstanceOfferingInventory instanceOfferingInventory = env.inventoryByName("instanceOffering")
        ImageInventory imageInventory = env.inventoryByName("image1")
        L3NetworkInventory l3NetworkInventory = env.inventoryByName("l3")

        CreateVmInstanceAction action = new CreateVmInstanceAction()
        action.name = "JustCreatedVm"
        action.rootDiskOfferingUuid = diskOfferingInventory.uuid
        action.instanceOfferingUuid = instanceOfferingInventory.uuid
        action.imageUuid = imageInventory.uuid
        action.l3NetworkUuids = [l3NetworkInventory.uuid]
        action.strategy = VmCreationStrategy.JustCreate.toString()
        action.sessionId = adminSession()
        CreateVmInstanceAction.Result result = action.call()

        destroyVmInstance {
            uuid = result.value.inventory.uuid
        }

        VmInstanceVO vo = dbFindByUuid(result.value.inventory.uuid, VmInstanceVO.class)
        assert vo == null
    }

    @Override
    void clean() {
        env.delete()
    }
}

我們先從跳轉到extends的SubCase中:

package org.zstack.testlib

/**
 * Created by xing5 on 2017/2/22.
 */
abstract class SubCase extends Test implements Case {
    final void run() {
        try {
            environment()
            test()
        } catch (Throwable t) {
            logger.warn("a sub case [${this.class}] fails, ${t.message}", t)
            collectErrorLog()
            throw t
        } finally {
            logger.info("start cleanup for case ${this.class}")
            try{
                clean()
            }catch (Throwable t){
                collectErrorLog()
                throw t
            }
        }
    }

    @Override
    protected void runSubCases() {
        throw new Exception("runSubCases() cannot be called in a SubCase")
    }
}

從簽名中可以看到,其繼承于Test,并實現了Case接口中的方法,我們看一下 Case

package org.zstack.testlib

/**
 * Created by xing5 on 2017/3/3.
 */
interface Case {
    void environment()
    void test()
    void run()
    void clean()
}

這里定義一個SubCase的基本行為:

environment:構建一個環境

test:用于跑Case本身

run:用于跑SubCase

clean:清理環境。這是SubCase必須關注的,不然會導致環境中含有臟數據

Test中,我們也可以看到定義里幾個關鍵抽象函數,用于定義一個Case的行為:

    abstract void setup()
    abstract void environment()
    abstract void test()

所以一個Case必須實現Test中的接口以及Case中的clean方法。

一般在setup中,會將依賴的Bean按需加載進來。這在前面提到過;而environment則會構建出一個環境。Grovvy對DSL支持較好,所以整個環境的構建代碼可讀性極強,本質上每個DSL都對應了一個Spec,而Sepc對應了一個ZStack的SDK創建調用——即XXXAction。而XXXAction則通過HTTP調用ZStack的API接口。

平時在測試中大家可能會為了Build一個環境直接對數據庫進行操作。例如:

xxxRepo.save(new Object());

但在ZStack中并不是一個很好的方案——一個Iaas中的資源依賴及狀態變動的關系是錯綜復雜的,因此調用外部的API來創建資源是一個明智的選擇。同時也可以測試SDK和API的行為是否是期待的。

在clean中也是如此。會調用ZStack本身的Cascade邏輯進行資源清理。打開EnvSpec.Grovvy可以看到

static List deletionMethods = [
            [CreateZoneAction.metaClass, CreateZoneAction.Result.metaClass, DeleteZoneAction.class],
            [AddCephBackupStorageAction.metaClass, AddCephBackupStorageAction.Result.metaClass, DeleteBackupStorageAction.class],
            [AddCephPrimaryStorageAction.metaClass, AddCephPrimaryStorageAction.Result.metaClass, DeletePrimaryStorageAction.class],
            [AddCephPrimaryStoragePoolAction.metaClass, AddCephPrimaryStoragePoolAction.Result.metaClass, DeleteCephPrimaryStoragePoolAction.class],
            [CreateEipAction.metaClass, CreateEipAction.Result.metaClass, DeleteEipAction.class],
            [CreateClusterAction.metaClass, CreateClusterAction.Result.metaClass, DeleteClusterAction.class],
            [CreateDiskOfferingAction.metaClass, CreateDiskOfferingAction.Result.metaClass, DeleteDiskOfferingAction.class],
            [CreateInstanceOfferingAction.metaClass, CreateInstanceOfferingAction.Result.metaClass, DeleteInstanceOfferingAction.class],
            [CreateAccountAction.metaClass, CreateAccountAction.Result.metaClass, DeleteAccountAction.class],
            [CreatePolicyAction.metaClass, CreatePolicyAction.Result.metaClass, DeletePolicyAction.class],
            [CreateUserGroupAction.metaClass, CreateUserGroupAction.Result.metaClass, DeleteUserGroupAction.class],
            [CreateUserAction.metaClass, CreateUserAction.Result.metaClass, DeleteUserAction.class],
            [AddImageAction.metaClass, AddImageAction.Result.metaClass, DeleteImageAction.class],
            [CreateDataVolumeTemplateFromVolumeAction.metaClass, CreateDataVolumeTemplateFromVolumeAction.Result.metaClass, DeleteImageAction.class],
            [CreateRootVolumeTemplateFromRootVolumeAction.metaClass, CreateRootVolumeTemplateFromRootVolumeAction.Result.metaClass, DeleteImageAction.class],
            [CreateL2NoVlanNetworkAction.metaClass, CreateL2NoVlanNetworkAction.Result.metaClass, DeleteL2NetworkAction.class],
            [CreateL2VlanNetworkAction.metaClass, CreateL2VlanNetworkAction.Result.metaClass, DeleteL2NetworkAction.class],
            [AddIpRangeByNetworkCidrAction.metaClass, AddIpRangeByNetworkCidrAction.Result.metaClass, DeleteIpRangeAction.class],
            [CreateL3NetworkAction.metaClass, CreateL3NetworkAction.Result.metaClass, DeleteL3NetworkAction.class],
            [CreateSchedulerJobAction.metaClass, CreateSchedulerJobAction.Result.metaClass, DeleteSchedulerJobAction.class],
            [CreateSchedulerTriggerAction.metaClass, CreateSchedulerTriggerAction.Result.metaClass, DeleteSchedulerTriggerAction.class],
            [CreateVmInstanceAction.metaClass, CreateVmInstanceAction.Result.metaClass, DestroyVmInstanceAction.class],
            [CreateDataVolumeFromVolumeSnapshotAction.metaClass, CreateDataVolumeFromVolumeSnapshotAction.Result.metaClass, DeleteDataVolumeAction.class],
            [CreateDataVolumeFromVolumeTemplateAction.metaClass, CreateDataVolumeFromVolumeTemplateAction.Result.metaClass, DeleteDataVolumeAction.class],
            [CreateDataVolumeAction.metaClass, CreateDataVolumeAction.Result.metaClass, DeleteDataVolumeAction.class],
            [CreateVolumeSnapshotAction.metaClass, CreateVolumeSnapshotAction.Result.metaClass, DeleteVolumeSnapshotAction.class],
            [AddKVMHostAction.metaClass, AddKVMHostAction.Result.metaClass, DeleteHostAction.class],
            [CreateLoadBalancerAction.metaClass, CreateLoadBalancerAction.Result.metaClass, DeleteLoadBalancerAction.class],
            [AddLocalPrimaryStorageAction.metaClass, AddLocalPrimaryStorageAction.Result.metaClass, DeletePrimaryStorageAction.class],
            [AddImageStoreBackupStorageAction.metaClass, AddImageStoreBackupStorageAction.Result.metaClass, DeleteBackupStorageAction.class],
            [AddNfsPrimaryStorageAction.metaClass, AddNfsPrimaryStorageAction.Result.metaClass, DeletePrimaryStorageAction.class],
            [CreatePortForwardingRuleAction.metaClass, CreatePortForwardingRuleAction.Result.metaClass, DeletePortForwardingRuleAction.class],
            [CreateSecurityGroupAction.metaClass, CreateSecurityGroupAction.Result.metaClass, DeleteSecurityGroupAction.class],
            [AddSftpBackupStorageAction.metaClass, AddSftpBackupStorageAction.Result.metaClass, DeleteBackupStorageAction.class],
            [AddSharedMountPointPrimaryStorageAction.metaClass, AddSharedMountPointPrimaryStorageAction.Result.metaClass, DeletePrimaryStorageAction.class],
            [CreateVipAction.metaClass, CreateVipAction.Result.metaClass, DeleteVipAction.class],
            [CreateVirtualRouterOfferingAction.metaClass, CreateVirtualRouterOfferingAction.Result.metaClass, DeleteInstanceOfferingAction.class],
            [CreateWebhookAction.metaClass, CreateWebhookAction.Result.metaClass, DeleteWebhookAction.class],
            [CreateBaremetalPxeServerAction.metaClass, CreateBaremetalPxeServerAction.Result.metaClass, DeleteBaremetalPxeServerAction.class],
            [CreateBaremetalChassisAction.metaClass, CreateBaremetalChassisAction.Result.metaClass, DeleteBaremetalChassisAction.class],
            [CreateBaremetalHostCfgAction.metaClass, CreateBaremetalHostCfgAction.Result.metaClass, DeleteBaremetalHostCfgAction.class],
            [CreateMonitorTriggerAction.metaClass, CreateMonitorTriggerAction.Result.metaClass, DeleteMonitorTriggerAction.class],
            [CreateEmailMonitorTriggerActionAction.metaClass, CreateEmailMonitorTriggerActionAction.Result.metaClass, DeleteMonitorTriggerActionAction.class],
            [CreateEmailMediaAction.metaClass, CreateEmailMediaAction.Result.metaClass, DeleteMediaAction.class],
            [AddLdapServerAction.metaClass, AddLdapServerAction.Result.metaClass, DeleteLdapServerAction.class],
            [SubmitLongJobAction.metaClass, SubmitLongJobAction.Result.metaClass, DeleteLongJobAction.class],
    ]

設置了對應的createAction和deleteAction,用于清理環境時調用。這樣同時也對Cascade邏輯進行了Cover。

利用松耦合進行靈活的測試

如果看過ZStack的Case,可以看到很多類似的方法:

env.afterSimulator

env.simulator

env.message

這幾個方法用來hook Message和HTTP Request。由于在ZStack中各個組件的通信都由Message來完成,對于Agent的請求則是統一通過HTTP來完成。這樣在TestCase就可以任意模擬任何組件及agent的狀態,讓Case有極強的實用性——也保證了ManagentMent Node的邏輯健壯。

在Java Web應用中的MockMvc實踐自動化測試

ZStack的SDK本質上是包裝了一層HTTP Path,利用通用的協議便于開發者進行開發或測試。而在傳統的Java WEB應用中,一般會通過MockMvc進行測試。其本質也是通過調用每個API的Path傳參來進行測試。接下來來看一個demo:

import com.camile.base.Utils.JsonUtils;
import com.camile.base.common.CommonResponse;
import com.camile.base.common.error.ResponseCode;
import com.camile.base.common.utils.MD5Util;
import com.camile.base.data.dao.UserRepository;
import com.camile.base.data.dto.user.*;
import com.camile.base.data.entity.UserEntity;
import com.camile.base.data.vo.UserVO;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.http.HttpSession;
import java.util.Map;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
 * Created by Camile 
 * 1.用戶注冊
 * 2.用戶登錄,測試自己是否處于登錄狀態,并執行更新信息、修改密碼操作
 * 3.用戶登出,更新信息、在線修改密碼,應全部失敗。
 * 4.用戶用新信息登錄,成功
 * 5.用戶登出,測試自己是否處于登錄狀態,走忘記密碼流程
 * 6.修改后再次登錄,成功
 */
@Slf4j
@Transactional
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class UserBasicTests {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private WebApplicationContext context;
    private String uuid;
    private HttpSession session;
    private MockMvc mvc;
    private ObjectMapper mapper;
    private final String email = "487643862@qq.com";
    private String password = "newPassword";
    private final String question = "are you ok ?";
    private final String answer = "im fine";
    private final String name = "camile";
    private final String phone = "13043769014";
    private String updateName = "camile1";
    private String updateEmail = "587643862@qq.com";
    private String updatePhone = "13834671096";
    @Before
    public void setUp() throws Exception {
        mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
        mapper = new ObjectMapper();
    }
    @Test
    public void test() throws Exception {
        testRegisterSuccess();
        testIsLoginFailure();
        testLoginSuccess();
        testIsLoginSuccess();
        testUpdateInformationSuccess();
        testOnlineRestPwdSuccess();
        testLoginOutSuccess();
        testUpdateInformationFailure();
        testOnlineRestPwdFailure();
        testloginWithOldPwdFailure();
        testLoginWithNewInfoSuccess();
        testLoginOutSuccess();
        testForgetPwdAndResetSuccess();
        testLoginWithNewInfoSuccess();
    }
    private void testRegisterSuccess() throws Exception {
        UserAllPropertyDTO dto = new UserAllPropertyDTO();
        dto.setEmail(email);
        dto.setPassword(password);
        dto.setQuestion(question);
        dto.setAnswer(answer);
        dto.setName(name);
        dto.setPhone(phone);
        String registerJson = JsonUtils.ObjectToJson(dto);
        MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/user/register.do")
                .contentType(MediaType.APPLICATION_JSON)
                .content(registerJson)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(response.getCode(), ResponseCode.Success.getCode());
        UserVO vo = JsonUtils.jsonToObject((Map) response.getData(), UserVO.class);
        Assert.assertNotNull(userRepository.findByUuid(vo.getUuid()));
        uuid = vo.getUuid();
        session = result.getRequest().getSession();
    }
    private void testIsLoginFailure() throws Exception { // never login
        MvcResult result = mvc.perform(MockMvcRequestBuilders.get(String.format("/user/isLogin.do?uuid=%s", uuid))
                .session((MockHttpSession) session)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(response.getCode(), ResponseCode.NeedLogin.getCode());
        session = result.getRequest().getSession();
    }
    private void testLoginSuccess() throws Exception {
        UserLoginDTO dto = new UserLoginDTO(name, password);
        String loginJson = JsonUtils.ObjectToJson(dto);
        MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/user/login.do")
                .session((MockHttpSession) session)
                .contentType(MediaType.APPLICATION_JSON)
                .content(loginJson)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(response.getCode(), ResponseCode.Success.getCode());
        session = result.getRequest().getSession();
    }
    private void testIsLoginSuccess() throws Exception {
        MvcResult result = mvc.perform(MockMvcRequestBuilders.get(String.format("/user/isLogin.do?uuid=%s", uuid))
                .session((MockHttpSession) session)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(ResponseCode.Success.getCode(), response.getCode());
        session = result.getRequest().getSession();
    }
    private void testUpdateInformationSuccess() throws Exception {
        UserDTO dto = new UserDTO();
        dto.setUuid(uuid);
        dto.setName(updateName);
        dto.setEmail(updateEmail);
        dto.setPhone(updatePhone);
        String updateJson = JsonUtils.ObjectToJson(dto);
        MvcResult result = mvc.perform(MockMvcRequestBuilders.put("/user/information.do")
                .session((MockHttpSession) session)
                .contentType(MediaType.APPLICATION_JSON)
                .content(updateJson)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(response.getMsg(), ResponseCode.Success.getCode(), response.getCode());
        UserEntity entity = userRepository.findByUuid(uuid);
        UserVO vo = JsonUtils.jsonToObject((Map) response.getData(), UserVO.class);
        Assert.assertNotNull(entity);
        Assert.assertEquals(vo.getName(), entity.getName());
        Assert.assertEquals(vo.getPhone(), entity.getPhone());
        Assert.assertEquals(vo.getEmail(), entity.getEmail());
        Assert.assertEquals(vo.getEmail(), updateEmail);
        Assert.assertEquals(vo.getPhone(), updatePhone);
        Assert.assertEquals(vo.getName(), updateName);
        session = result.getRequest().getSession();
    }
    private void testOnlineRestPwdSuccess() throws Exception {
        UserResetPwdDTO dto = new UserResetPwdDTO();
        dto.setUuid(uuid);
        dto.setOldPassword(password);
        dto.setNewPassword("12345678");
        password = "12345678";
        String resetPwdJson = JsonUtils.ObjectToJson(dto);
        MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/user/onlineResetPwd.do")
                .session((MockHttpSession) session)
                .contentType(MediaType.APPLICATION_JSON)
                .content(resetPwdJson)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(response.getMsg(), response.getCode(), ResponseCode.Success.getCode());
        session = result.getRequest().getSession();
        UserEntity userEntity = userRepository.findByUuid(uuid);
        Assert.assertEquals(userEntity.getPassword(), MD5Util.MD5EncodeUtf8(password));
    }
    private void testLoginOutSuccess() throws Exception {
        MvcResult result = mvc.perform(MockMvcRequestBuilders.post(String.format("/user/loginOut.do?uuid=%s", uuid))
                .session((MockHttpSession) session)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(response.getCode(), ResponseCode.Success.getCode());
        session = result.getRequest().getSession();
    }
    private void testUpdateInformationFailure() throws Exception {
        String updateName = "camile2";
        String updateEmail = "687643862@qq.com";
        String updatePhone = "14834671096";
        UserDTO dto = new UserDTO();
        dto.setUuid(uuid);
        dto.setName(updateName);
        dto.setEmail(updateEmail);
        dto.setPhone(updatePhone);
        String updateJson = JsonUtils.ObjectToJson(dto);
        MvcResult result = mvc.perform(MockMvcRequestBuilders.put("/user/information.do")
                .session((MockHttpSession) session)
                .contentType(MediaType.APPLICATION_JSON)
                .content(updateJson)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(response.getMsg(), ResponseCode.Failure.getCode(), response.getCode());
        session = result.getRequest().getSession();
    }
    private void testOnlineRestPwdFailure() throws Exception {
        UserResetPwdDTO dto = new UserResetPwdDTO();
        dto.setUuid(uuid);
        dto.setOldPassword(password);
        dto.setNewPassword("123456789");
        String resetPwdJson = JsonUtils.ObjectToJson(dto);
        MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/user/onlineResetPwd.do")
                .session((MockHttpSession) session)
                .contentType(MediaType.APPLICATION_JSON)
                .content(resetPwdJson)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(response.getMsg(), response.getCode(), ResponseCode.Failure.getCode());
        session = result.getRequest().getSession();
        UserEntity userEntity = userRepository.findByUuid(uuid);
        Assert.assertNotEquals(userEntity.getPassword(), MD5Util.MD5EncodeUtf8("123456789"));
    }
    private void testloginWithOldPwdFailure() throws Exception {
        UserLoginDTO dto = new UserLoginDTO(name, "newPassword");
        String loginJson = JsonUtils.ObjectToJson(dto);
        MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/user/login.do")
                .session((MockHttpSession) session)
                .contentType(MediaType.APPLICATION_JSON)
                .content(loginJson)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(response.getCode(), ResponseCode.UserInfoError.getCode());
        session = result.getRequest().getSession();
    }
    private void testLoginWithNewInfoSuccess() throws Exception {
        UserLoginDTO dto = new UserLoginDTO(updateName, password);
        String loginJson = JsonUtils.ObjectToJson(dto);
        MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/user/login.do")
                .session((MockHttpSession) session)
                .contentType(MediaType.APPLICATION_JSON)
                .content(loginJson)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(ResponseCode.Success.getCode(), response.getCode());
        session = result.getRequest().getSession();
    }
    private void testForgetPwdAndResetSuccess() throws Exception {
        MvcResult result = mvc.perform(MockMvcRequestBuilders.get(String.format("/user/forget/question?name=%s", updateName))
                .session((MockHttpSession) session)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        String content = result.getResponse().getContentAsString();
        CommonResponse response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(response.getMsg(), ResponseCode.Success.getCode(), response.getCode());
        session = result.getRequest().getSession();
        String question = (String) response.getData();
        Assert.assertEquals(question, this.question);
        UserQuestionDTO dto = new UserQuestionDTO();
        dto.setName(updateName);
        dto.setQuestion(question);
        dto.setAnswer(answer);
        String questionJson = JsonUtils.ObjectToJson(dto);
        result = mvc.perform(MockMvcRequestBuilders.post("/user/forget/checkAnswer.do")
                .session((MockHttpSession) session)
                .contentType(MediaType.APPLICATION_JSON)
                .content(questionJson)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        content = result.getResponse().getContentAsString();
        response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(ResponseCode.Success.getCode(), response.getCode());
        session = result.getRequest().getSession();
        String token = (String) response.getData();
        UserForgetResetPwdDTO userForgetResetPwdDTO = new UserForgetResetPwdDTO();
        userForgetResetPwdDTO.setForgetToken(token);
        userForgetResetPwdDTO.setName(updateName);
        userForgetResetPwdDTO.setNewPassword("superpwd!");
        password = "superpwd!";
        String resetPwdDTO = JsonUtils.ObjectToJson(userForgetResetPwdDTO);
        result = mvc.perform(MockMvcRequestBuilders.post("/user/forget/resetPassword.do")
                .session((MockHttpSession) session)
                .contentType(MediaType.APPLICATION_JSON)
                .content(resetPwdDTO)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();
        content = result.getResponse().getContentAsString();
        response = mapper.readValue(content, CommonResponse.class);
        Assert.assertEquals(response.getMsg(), ResponseCode.Success.getCode(), response.getCode());
        session = result.getRequest().getSession();
        UserEntity userEntity = userRepository.findByUuid(uuid);
        Assert.assertEquals(userEntity.getPassword(), MD5Util.MD5EncodeUtf8(password));
    }
}

我們可以看到MockMvc的鏈式調用讓代碼可讀性變得極強:

       MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/user/register.do")
                .contentType(MediaType.APPLICATION_JSON)
                .content(registerJson)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andReturn();

在這里,我們對MockMvc的對象設置了相應的URL以及Content類型、數據,并且期待了它的狀態碼。

小結

在這篇文章中,筆者和大家一起分析了ZStack的自動化測試,以及在JavaWeb應用中常見的測試方法。當然,這些測試都屬于集成測試。而單元測試以及如何在自己的應用中編寫一套更強大的自動測試框架這類主題,之后有機會筆者會再與大家分享。

擴展閱讀:ZStack:管理節點基于模擬器的Integration Test框架

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/68384.html

相關文章

  • ZStack源碼剖析之二次開發——Debug的常用技巧

    摘要:本文首發于泊浮目的專欄在前文源碼剖析之二次開發可擴展框架中,我們大概的了解了如何在中進行二次開發。在還有相關的日志,有興趣的讀者可以自行搜索。掛斷點在掛斷點之前,請確定自己的開放了相應的端口。之后記得使用關掉。 本文首發于泊浮目的專欄:https://segmentfault.com/blog... 在前文 ZStack源碼剖析之二次開發——可擴展框架中,我們大概的了解了如何在ZSt...

    taowen 評論0 收藏0
  • 小談日志與其實踐

    摘要:對于日志級別的分類,有以下參考表示需要立即被處理的系統級錯誤。注意日志的切片設置,以免文件過大不方便操作。過期的日志定期清理。 本文首發于泊浮目的專欄:https://segmentfault.com/blog... 前言 前陣子在論壇上看到一個問題,大致的意思就是日志該怎么打?或者說是,我們應該在日志中打印出哪些內容? 看了該問題,筆者真是有所感慨:從實習到現在,從接的外包小項目到...

    lidashuang 評論0 收藏0
  • 小談日志與其實踐

    摘要:對于日志級別的分類,有以下參考表示需要立即被處理的系統級錯誤。注意日志的切片設置,以免文件過大不方便操作。過期的日志定期清理。 本文首發于泊浮目的專欄:https://segmentfault.com/blog... 前言 前陣子在論壇上看到一個問題,大致的意思就是日志該怎么打?或者說是,我們應該在日志中打印出哪些內容? 看了該問題,筆者真是有所感慨:從實習到現在,從接的外包小項目到...

    pinecone 評論0 收藏0
  • 小談日志與其實踐

    摘要:對于日志級別的分類,有以下參考表示需要立即被處理的系統級錯誤。注意日志的切片設置,以免文件過大不方便操作。過期的日志定期清理。 本文首發于泊浮目的專欄:https://segmentfault.com/blog... 前言 前陣子在論壇上看到一個問題,大致的意思就是日志該怎么打?或者說是,我們應該在日志中打印出哪些內容? 看了該問題,筆者真是有所感慨:從實習到現在,從接的外包小項目到...

    netmou 評論0 收藏0
  • 小談日志與其實踐

    摘要:對于日志級別的分類,有以下參考表示需要立即被處理的系統級錯誤。注意日志的切片設置,以免文件過大不方便操作。過期的日志定期清理。 本文首發于泊浮目的專欄:https://segmentfault.com/blog... 前言 前陣子在論壇上看到一個問題,大致的意思就是日志該怎么打?或者說是,我們應該在日志中打印出哪些內容? 看了該問題,筆者真是有所感慨:從實習到現在,從接的外包小項目到...

    AprilJ 評論0 收藏0

發表評論

0條評論

EastWoodYang

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<