IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> Android单元测试 ->知识整理及分享 -> 正文阅读

[开发测试]Android单元测试 ->知识整理及分享

Android单元测试

单元测试?

What?

项目中为了测试某一个代码单元而写的测试代码;用于执行项目中的目标函数并验证其逻辑状态或者结果。这些代码是白盒测试,能够检测目标代码的准确性和可靠性,在打包时单元测试的代码并不会被编译进入release apk中。

Why?

  1. 提高信心

单元测试不能百分之百保证在集成联调时能够完全正确运行,但可以保证每一代码单元测试通过。

  1. 方便代码重构

使用单元测试可以边重构边写单元测试,保证重构没有破坏原有的代码逻辑的准确性。

  1. 写单元测试本身就是一次小范围的代码重构

这个过程中,可以发现逻辑设计上的问题,代码编写方面的问题,比如一些边界条件处理、空对象的保护和类构造时参数的依赖问题,还有一些对Android Context的依赖问题。

  1. 节约开发时间

如果没有单元测试的话,我们coding时为了调试某个功能,看界面是否显示正确,把APP运行起来,如果有错的话,改一点东西,再运行起来。。。有了单元测试,开发过程中可以更少的把APP运行起来,一两分钟的等待就可以验证代码逻辑是否正确,速度相对来说快很多。此外,通过单元测试能帮我们减少bug,从而减少了调试bug和fix bug的时间

  1. 更快的发现bug

如果没有单元测试,我们就需要在最后的集成联调中才能发现自己模块的问题,一旦问题比较严重的话,可能会让自己感觉有压力和恐慌。但是通过单元测试,可以有多一层的保证,可以更早的发现问题和解决问题,在集成时让自己更加闲庭信步。

一、Android现有测试框架及其优缺点

  1. JUnit4

    1. 测试对象及环境:针对 无复杂依赖情况;针对 非私有、非静态、非全局的方法、类的测试;
    2. 用的最多的一个测试框架,Android Studio创建的工程中就默认集成了JUnit4,并添加了dependencies;
    3. 对应的单元测试代码则是放在src/test/java目录中,
    4. 编写:与IDEA类似,
@Test

public void testadd(int num1, int num2) {

    MainActivity mainActivity = new MainActivity();    //before;创建待测类的对象

    int sum = mainActivity.add(1,2);                   //on:调用待测方法

    Assert.assertEquals(3,sum);                        //after:通过断言检测结果

}
  1. 运行:选中方法,右键 run 即可;

  2. 主要测试对象

    1. 有明确的返回值;做单元测试时,只需调用这个函数,验证其返回值是否符合预期结果。
    2. 这个函数只改变其对象内部的一些属性或者状态,函数本身没有返回值,就验证它所改变的属性和状态。
    3. 一些函数没有返回值,也没有直接改变哪个值的状态,这就需要验证其行为,比如点击事件。???
    4. 对于 b、c 两种情况,往往是验证目标方法中的某个对象的某个方法是否得到了调用,或者验证目标方法中的某个对象的某个状态是否发生改变,以此来验证目标方法是否按照我们想要的逻辑进行调用;
  3. 问题:对于项目中依赖资源复杂情况,处理困难;对于对象、集合、Map等数据结构的比较(断言的可读性不友好),可使用Hamcest框架进行比较;

  4. Mockito

    1. 测试对象及环境:针对 复杂依赖情况;针对 非私有、非静态、非全局的方法、类的测试;

    2. 在测试环境中,通过Mockito mock出其他的依赖对象,用来替换真实的对象,使得待测的目标方法被隔离起来,

      避免外界因素的影响和依赖

      ,能在我们预设的环境中执行,以达到两个目的:

      1. 验证指定方法的调用情况,调用了多少次,参数是什么等等;
      2. 指定该对象的某些方法的行为,返回特定的值,或是执行特定的动作;
    3. 问题:生成mock对象的原理有其局限性,如final类型、private类型以及静态类型的方法不能mock;

  5. PowerMockito

    1. 测试对象及环境:针对 复杂依赖情况;针对 私有、静态、全局的方法、类的测试;
    2. 扩展了其它mock框架;PowerMock基本上 cover 了 Mockito 不能支持的 case;
    3. 使用JUnit4+Mockito+PowerMockito可完成大部分java测试
    4. Powermock提供了mock和spy两种方式,对于 Activity 的私有方法的调用验证通常需要做方法模拟。mock 和 spy 都可以实现。
    5. 问题:对于依赖 Android SDK 的对象(如Activity,Button等),测试非常头疼;
  6. Robolectric

    1. 测试对象及环境:针对 依赖 Android SDK 的对象(如Activity,Button等)的测试
    2. 通过实现一套JVM能运行的Android代码,从而做到脱离Android环境进行测试。
    3. 可实现UI测试,查询一个控件,模拟点击,验证逻辑;
    4. JUnit4+Mockito+PowerMockito+Robolectric
    5. 问题:因为我们的项目都是在Activity里面写的,一些业务逻辑都是使用私有方法,那么相对私有方法做验证,通过查询控件和通过UI的展示来验证逻辑的正确与否,十分的复杂。需要使用Powermock
    6. 注意PowermockRobolectric存在着兼容问题,如果出现问题无法解决,可尝试放弃Robolectric
  7. UIAutomator和Espresso;

Google开源的测试框架,基于Instrumentation,更偏向于UI方面的自测化测试。

Espresso功能强大、执行速度很快的,但是它有一个重要的局限:只可以在被测App的Context中操作。意味着下列App自动化测试需求无法实现:应用的推送消息、同步联系人、从另一个应用程序进入被测App。

UIAutomator 2.0 发布后可以实现上述功能;采用脚本语言编写,集成失败…UIAutomator集成测试失败;

  1. robotium;UI测试用例

  2. ActivityUnitTestCase、ActivityInstrumentationTestCase2

由Android提供的Instrumentation系统如,将单元测试代码运行在模拟器或者是真机上。虽然这种方式可以work,但是速度非常慢。

二、确定Android 测试框架

JUnit4MockitoPowerMockitoRobolectricUIAuutomator / EspressorobotiumActivityUnitTestCase / ActivityInstrumentationTestCase2
项目中依赖复杂的情况???
依赖Android SDK 的情况?
UI测试???
测试私有、全局、静态?

JUnit4 + Mockito + PowerMockito + Robolectric

使用:JUnit4 + PowerMockito

三、单元测试怎么写,非界面的逻辑部分的单元测试怎么写

在Android studio project中,源代码默认放在src/main/java下面的,

对应的Java相关的单元测试代码则是放在src/test/java目录中;

src/androidTest/java中存放的是Android相关的单元测试代码

  1. JUnit4

依赖:默认是有的:testImplementation “junit:junit:$junit_version”

以 tosee-sdk 为例;src/main/java/tech/tosee/combine/models/TSPeer.kt

  1. 单元测试
  2. 非界面的单元测试
  • 创建测试类。右键类名,选择GOTO 选择Test

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-94cSzLBp-1626681578596)(https://vbqlkb723k.feishu.cn/space/api/box/stream/download/asynccode/?code=YmU1OTZiNTJjYmY2MDlmNWNhM2ZkYTgzMWRlZDZiYzlfVldpWk4yZ3pINXBDRUlCMWJNQ3prcHJxS0dZV2tRdnRfVG9rZW46Ym94Y25raVVhY3lPNWhSb1VFdlJTV2lJREpmXzE2MjY2ODE0NTQ6MTYyNjY4NTA1NF9WNA)]

  • 选择JUnit4;勾选待测试的方法或属性(私有方法没有显示);注意,点击OK后会提示保存目录:Java相关代码则是放在src/test/java目录中;Android相关的单元测试代码在src/androidTest/java

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8FfFWUeu-1626681578597)(https://vbqlkb723k.feishu.cn/space/api/box/stream/download/asynccode/?code=NzllZDgzOThiOGFmMDEyMTQ2M2YzMTZiMjcwOWM4MGRfZVRwY3VlYUJoeUx2bTNNd21aNnl0Ym5lbkNhQnV2ck9fVG9rZW46Ym94Y24zaWhXRmdqRmNpRGJLTnFCeG9VMVBkXzE2MjY2ODE0NTQ6MTYyNjY4NTA1NF9WNA)]

  • 代码补全
@Test

fun testEquals() {

    //before 实例化 待测试的目标类,以及设计一些前提条件:

    val tsPeer: TSPeer = TSPeer("userId", "gmsUserId", "nickname", "merchantId", "rtcUserId")

    //on 执行操作,调用待测试的那个方法,同时获得结果:

    val equals = tsPeer.equals(TSPeer("userid", "gmsUserId", "nickName", "merchantid", "rtcUserid"))

    print("================================" + equals)//这个不被打

    Log.i(TAG, "testEquals: ")

    //after验证结果,通过断言来验证结果是否与预期一样:

    assertTrue(equals)

}
  • 运行测试方法。右键方法名,run

注解:

@BeforeClass:针对所有测试,只执行一次,且必须为static void

@Before:初始化方法 对于每一个测试方法都要执行一次(注意与BeforeClass区别,后者是对于所有方法执行一次)

@Test:测试方法,在这里可以测试期望异常和超时时间

@Test(expected=ArithmeticException.class)检查被测方法是否抛出ArithmeticException异常

@Ignore:忽略的测试方法

@After:释放资源 对于每一个测试方法都要执行一次(注意与AfterClass区别,后者是对于所有方法执行一次)

@AfterClass:针对所有测试,只执行一次,且必须为static void
  1. PowerMockito

  • 依赖:
testImplementation "org.mockito.kotlin:mockito-kotlin:3.2.0"

// PowerMock brings in the mockito dependency

testImplementation "org.powermock:powermock-module-junit4:2.0.4"

testImplementation "org.powermock:powermock-module-junit4-rule:2.0.4"

testImplementation "org.powermock:powermock-api-mockito2:2.0.4"

testImplementation "org.powermock:powermock-classloading-xstream:2.0.4"

如遇问题推荐阅读:Android 单元测试之PowerMock

  • 注解:
@RunWith(PowerMockRunner.class)

@PrepareForTest({YourClassWithEgStaticMethod.class})

@PowerMockIgnore("javax.management.*")

若测试用例没有用@PrepareForTest,那么不用加@RunWith(PowerMockRunner.class),反之亦然。

当你需要使用PowerMock进行Mock静态、final、私有方法等时候,就需要加@PrepareForTest。要么使用这种注解的方式:

@RunWith(PowerMockRunner.class)

@PrepareForTest({YourClassWithEgStaticMethod.class})

要么使用注解加代码的方式

@PrepareForTest({YourClassWithEgStaticMethod.class})

MockitoAnnotations.initMocks(this);

注:@PrepareForTest({Example1.class, Example2.class, ...}) //声明多个静态类

  1. 普通Mock:Mock参数传递的对象(不需要加注解)

  • 待测代码
class CommonExampleKotlin {

    fun callArgumentInstance(file: File): Boolean {

        return file.exists()

    }

}
  • 测试代码
class CommonExampleKotlinTest {

    @Test

    fun testCallArgumentInstance() {

        //1。创建一个mock对象

        val file = PowerMockito.mock(File::class.java)

        val commonExample = CommonExample()

        //2。指定mock对象具体的行为

        PowerMockito.`when`(file.exists()).thenReturn(true)

        //3。将mock对象作为参数传递给测试方法,执行测试方法。

        assertTrue(commonExample.callArgumentInstance(file))

    }

}
  1. Mock 方法内部new出来的对象

当使用 PowerMockito.whenNew 方法时,必须加注解 @PrepareForTest 和 @RunWith 。@PrepareForTest 里写的类是需要 mock 的 new 对象代码所在的类。

  • 待测代码 1
class CommonExampleKotlin {

    /**

     * 2) Mock方法内部new出来的对象

     */

    fun callArgumentInstance(path: String?): Boolean {

        val file = File(path)

        return file.exists()

    }

}
  • 测试代码 1
@Test

//@RunWith(PowerMockRunner::class.java)

@PrepareForTest(CommonExampleKotlin::class)

//2) Mock方法内部new出来的对象

fun testCallArgumentInstance2() {

    //代码实现RunWith

    MockitoAnnotations.initMocks(this);

    //1。创建一个mock对象

    val file = PowerMockito.mock(File::class.java)

    val commonExampleKotlin = CommonExampleKotlin()

    //2。指定当以参数为"fileName"创建File对象的时候,返回已经mock的File对象。

    PowerMockito.whenNew(File::class.java).withArguments("fileName").thenReturn(file)

    //3。指定mock对象具体的行为

    PowerMockito.`when`(file.exists()).thenReturn(true)

    //实际上此处该方法 并未成功创建文件,

    assertTrue(!commonExampleKotlin.callArgumentInstance("fileName"))

    val newFile = Mockito.mock(File::class.java)

    newFile.exists()

    Mockito.verify(newFile).exists()

}
  • 待测代码 2
public class EmployeeService {

    public int getTotalEmployee() {

        EmployeeDao employeeDao = new EmployeeDao();

        return employeeDao.getTotal();

    }

}
  • 测试代码 2
getTotalEmployee()因为测试的时候是不能修改这个方法的,不管里面是什么东西,局部变量我们也是无法触摸的,所以!智能模拟,不能更改,这个改正很可能造成系统的缺陷。不注意就完了。非常的需要小心,作为测试人员的话!



/**

 * 采用 PowerMock 进行测试

*/

@Test

public void testGetTotalEmployeeWithMock() {

    EmployeeDao employeeDao = PowerMockito.mock(EmployeeDao.class);

    try {

        //没得参数的够造!返回模拟的局部变量!

        PowerMockito.whenNew(EmployeeDao.class).withNoArguments()

          .thenReturn(employeeDao);

        PowerMockito.when(employeeDao.getTotal()).thenReturn(10);

        EmployeeService service = new EmployeeService();

        int total = service.getTotalEmployee();

        assertEquals(10, total);

        } catch (Exception e) {

            fail("测试失败.");

        }

    }

}
  1. Mock普通对象的 final 方法

  • 待测代码
class CommonDependency {

    /**

     * 3) Mock普通对象的final方法

     */

    final fun isAlive(): Boolean {

        // do something

        return false

    }

}
class CommonExampleKotlin {

    /**

     * 3) Mock普通对象的final方法

     */

    open fun callFinalMethod(example: CommonDependency): Boolean {

        return example.isAlive()

    }

}
  • 测试代码
@Test

//final方法所在的类。

@PrepareForTest(CommonDependency::class)

fun testCallFinalMethod() {

    val mock: CommonDependency = PowerMockito.mock(CommonDependency::class.java)

    val commonExampleKotlin = CommonExampleKotlin()

    PowerMockito.`when`(mock.isAlive()).thenReturn(true)

    assertTrue(commonExampleKotlin.callFinalMethod(mock))

}
  • 注意:如果使用 PowerMockito.mock 报错 ockito cannot mock/spy because : - final class

添加依赖:

//Mockito

testImplementation "org.mockito:mockito-inline:3.3.3"

androidTestImplementation 'org.mockito:mockito-android:3.3.3'

4. Mock静态类的静态方法

  • 待测代码
class CommonExampleKotlin {

    /**

     * 4) Mock普通类的静态方法

     */

    fun printUUID(): String {

       return Utils.generateNewUUId()

    }

}
  • 静态类
object MUtils {

    @JvmStatic

    open fun generateNewUUId(): String {

        return UUID.randomUUID().toString()

    }

}
  • 测试代码
//语句告诉JUnit用PowerMockRunner来执行测试。

@RunWith(PowerMockRunner::class)

//语句告诉PowerMock准备Employee类进行测试。适用于模拟final类或有final, private, static, native方法的类。

@PrepareForTest(Utils::class)

class CommonExampleKotlinTest {

    //4) ??????? Mock普通类的静态方法

    val res = "Return UUID"

    @Test

    fun testPrintUUID() {

        val commonExampleKotlin = CommonExampleKotlin()

        

        PowerMockito.mockStatic(MUtils::class.java)

        PowerMockito.`when`(MUtils.generateNewUUId()).thenReturn(res)

        print(commonExampleKotlin.printUUID())

        assert(res.equals(commonExampleKotlin.printUUID()))

    }

}
  1. Mock 私有方法

  • 待测方法
class CommonExampleKotlin {

    /**

     * 5) Mock 私有方法

     */

    fun callPrivateMethod(): Boolean {

        return isExist()

    }



    private fun isExist(): Boolean {

        return false

    }

}
  • 测试代码
//语句告诉JUnit用PowerMockRunner来执行测试。

@RunWith(PowerMockRunner::class)

//语句告诉PowerMock准备Employee类进行测试。适用于模拟final类或有final, private, static, native方法的类。

@PrepareForTest(CommonExampleKotlin::class)

class CommonExampleKotlinTest {

    //5)mock 私有方法

    @Test

    fun testCallPrivateMethod() {

        val mock:CommonExampleKotlin = PowerMockito.mock(CommonExampleKotlin::class.java)

        PowerMockito.`when`(mock.callPrivateMethod()).thenCallRealMethod()

        PowerMockito.`when`<Boolean>(mock, "isExist").thenReturn(true)

        print(mock.callPrivateMethod())

        assertTrue(mock.callPrivateMethod())

    }

}

6. Mock系统类的静态和final方法

  • 待测代码
class CommonExampleKotlin {

    /**

     * 6) Mock系统类的静态和final方法

     */

    fun callSystemStaticMethod(str: String?): String {

        return System.getProperty(str)

    }

}
  • 测试代码
//语句告诉JUnit用PowerMockRunner来执行测试。

@RunWith(PowerMockRunner::class)

//语句告诉PowerMock准备Employee类进行测试。适用于模拟final类或有final, private, static, native方法的类。

//@PrepareForTest(Utils::class)

@PrepareForTest(CommonExampleKotlin::class)

class CommonExampleKotlinTest {

    //6) Mock系统类的静态和final方法

    @Test

    fun testcallSystemStaticMethod() {

        val commonExample = CommonExampleKotlin();

        PowerMockito.mockStatic(System::class.java);

        PowerMockito.`when`<String>(System.getProperty("aaa")).thenReturn("bbb");

        assertEquals("bbb", commonExample.callSystemStaticMethod("aaa"));

    }

}

7. Mock普通类的私有变量

  • 待测代码
class CommonExampleKotlin {

    /**

     * 7) Mock普通类的私有变量

     */

    private val STATE_NOT_READY: Int = 0

    private val STATE_READY = 1

    private val mState = STATE_NOT_READY



    fun doSomethingIfStateReady(): Boolean {

        return if (mState == STATE_READY) {

            // DO some thing

            true

        } else {

            false

        }

    }

}
  • 测试代码
class CommonExampleKotlinTest {

    //7) Mock普通类的私有变量

    @Test

    fun testdoSomethingIfStateReady() {

        val sample = CommonExampleKotlin()

        Whitebox.setInternalState(sample, "mState", 1)

        assertTrue(sample.doSomethingIfStateReady())

    }

}

注:当需要mock私有变量mState的时候,不需要加注解@PrepareForTest和@RunWith,而是使用Whitebox来mock私有变量mState并注入你预设的变量值。

四、单元测试的覆盖率统计怎么做

  1. 概念:

程序中源代码被测试的比例和程度,所得比例称为代码覆盖率。

  1. 指标

    1. 分支(C1 Coverage):对所有的ifswitch语句计算分支覆盖率。统计在方法中分支执行数量、未执行数量的信息。但要注意,异常处理不在此计算范围内。
    2. 行(Lines):一行可能包含一条或多条指令,如果至少有一条指令被执行了,那么该行就算作是被执行了。
    3. 方法(Methods):每个非抽象方法至少包含一条指令。如果至少有一条指令被执行了,那么该方法就算作是被执行了。
    4. 类(Classes):如果类中至少有一个方法被执行了,那么该类就算作是被执行了。
    5. 指令(C0 Coverage):JaCoCo计数的最小单元是单一的Java字节码指令。指令覆盖率提供了关于字节码执行数量、未执行数量的信息。
    6. 圈复杂度(Cyclomatic Complexity):对非抽象方法计算圈复杂度,并汇总类、包和组的(圈)复杂度。这个值可以做为单元测试用例是否完全覆盖的参考。
  2. 使用方法

  • 点击 IDE 上侧的"Edit Configurations…":

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9LVRnYTq-1626681578598)(https://vbqlkb723k.feishu.cn/space/api/box/stream/download/asynccode/?code=MjViZmIzYjU5ODM0OGFlODg5MzljZTgyYWYxNmJhNDVfb3RyNVdDUnFVRmRxOWswbEZyUllGcjRjUlRUWWpxTE9fVG9rZW46Ym94Y25JWnI0akFHSTJkSm1lNGgzZ0VXN011XzE2MjY2ODE0NTQ6MTYyNjY4NTA1NF9WNA)]

  • 在"Choose coverage runner"中选择JaCoCo:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BPsOwIio-1626681578600)(https://vbqlkb723k.feishu.cn/space/api/box/stream/download/asynccode/?code=M2I3NTlkOTlhMzI1ODVjMTdjNTZjNDFlYWFlM2MwZWJfclp4ZjkxQVA3TGl4cE1sVEhwNW52Y0ZvbnE5OUtOcmdfVG9rZW46Ym94Y25wenJ5OUZPYXUwVWJ0SW5COFF5b0piXzE2MjY2ODE0NTQ6MTYyNjY4NTA1NF9WNA)]

  • 运行;右键类名,选择 run ‘…’ with Coverage

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cSHq3AIb-1626681578601)(https://vbqlkb723k.feishu.cn/space/api/box/stream/download/asynccode/?code=ODlhMmNlOTA2MzcwNTFkZTA4YzVmOWU4YTk3MjZmZDdfczR6SDZMcE1jMTZRbWxyMmtxelpqNGhWUlBEdGV5bVhfVG9rZW46Ym94Y252VnZKQlBHekhZVFZyWnlSanpRZGdkXzE2MjY2ODE0NTQ6MTYyNjY4NTA1NF9WNA)]

  • 运行完成后会展示 (Classes)、方法(Methods)、(Lines)等指标

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KVT78CsZ-1626681578602)(https://vbqlkb723k.feishu.cn/space/api/box/stream/download/asynccode/?code=NzE4ZTAzMjcxNjU1ZTZjZmUzYzk4YTE0ZjY0ZDMwYjJfR1VUeFBZS0hzWEl3QU9ZZmNEOHZDdWZocTNqbDJIZ3lfVG9rZW46Ym94Y25RUE4wRk43YklPN3JyeWF2ZGlzMXNmXzE2MjY2ODE0NTQ6MTYyNjY4NTA1NF9WNA)]

  • 点击左边栏 “Generate Coverage Report” 可以生成一份html版的所有指标的报告:
    在这里插入图片描述

在这里插入图片描述

  1. 参考文档

    1. Android单元测试框架-设计思路

    2. Jacoco:与Powermock有兼容性问题。

    3. Cobertra

    4. Android 使用 JaCoco 分析单元代码测试覆盖率

    5. Android单元测试/Ui测试+JaCoCo覆盖率统计

    6. Android UI自动化测试的代码覆盖率

附:

  1. ExoPlayer
    1. 是构建在Android低水平媒体API之上的一个应用层媒体播放器;
    2. ExoPlayer简单使用
    3. 官方文档
    4. ExoPlayer详解——入门(官方文档)
  2. 圈复杂度
  3. 其他方向
    在这里插入图片描述

如有侵权,请联系删帖。

推荐阅读:
Mockito&PowerMockito的原理与使用
Java单元测试技巧之PowerMock
史上最轻量?!阿里新型单元测试Mock工具开源了


注意

  1. 不必写每一个方法的测试方法;可以自己写@Test 类,而后在其内调用多个方法;——思路打开
  2. 写好单元测试
  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 23:05:08  更:2021-07-22 23:05:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 3:38:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码