在Sales force开发中完善测试类是开发者必经的一个环节,代码的部署需要保证至少75%的覆盖率,那么该如何写好测试类呢。

测试类定义格式如下:

 @isTest
private class MyTestClass {
@isTest static void myTest() {
// code_block
}
static testMethod void testName() {
// code_block
}
}

测试类允许声明为private或者public,一般来说,单元测试的测试类都声明为private,如果是DateFactory的话则声明为public,其中测试类不占用计算在APEX代码的限制中。

测试类的命名规范一般有两种:MyClassTest 或者 TestMyClassName

两种规范各有优劣,其中 MyClassTest紧随Apex类之后,便于查询与修改,TestMyClass则将所有测试类都集中在一起,便于打包。可以根据自己的习惯自行决定。

在测试类的写法上有两种选择

  • 用少量测试类覆盖远大于测试类的Apex类
  • 一个测试类对应一个Apex类

从项目规范上来说,应该一个测试类对应一个Apex类,从而保证不论是后期维护,还是功能变更又或者代码修改,都能保证代码的质量并且在部署时更加快捷;但是少量测试类覆盖多个Apex类同样也是一种选择,因为存在Apex类因为功能简单,专门写个测试类显得很“多余”,而且在测试类的交叉覆盖下,很多Apex类覆盖率自然就上去了,项目上线迭代的速度能得到很大程度的提高。

两种写测试类的优缺点很明显,少量测试类覆盖远大于测试类的Apex类,上线速度快,减少开发量,但是在后期维护乃至二期项目中需要花费更大的时间去处理测试类的问题,如果后来的开发者不熟悉之前的逻辑那需要的时间将更加漫长;一个测试类对应一个Apex类的写法在项目进行中的时候会占据不少的时间,但是好处就是代码结构清晰,后期维护的开发者不管熟不熟悉都将能游刃有余的处理之前的内容。

从长远的角度来说,我更推荐使用后一种,作为程序员,应该花60%的时间去思考逻辑以及最优的实现方式,然后花20%的时间去实现,最后花费20%的时间进行包括业务场景在内的测试。

写好的测试类能尽可能的验证你写的代码逻辑的正确性,提升你的代码质量,即使修改了之前的逻辑,执行你的测试方法也能知道有没有影响你之前的逻辑,方便进行回归测试。

说了这么多,来看一个示例吧。

 /*********
*
* @Author:ricardo
* @Time:2018-05-09
* @Function 华氏温度温度转换摄氏温度
*/
public class TemperatureConverter {
// Takes a Fahrenheit temperature and returns the Celsius equivalent.
public static Decimal FahrenheitToCelsius(Decimal fh) {
Decimal cs = (fh - 32) * 5/9;
return cs.setScale(2);
}
}

测试类如下

 @isTest
private class TestTemperatureConverter {
//正常输入
@isTest static void testWarmTemp() {
Decimal celsius = TemperatureConverter.FahrenheitToCelsius(70);
System.assertEquals(21.11,celsius);
}
//临界值
@isTest static void testFreezingPoint() {
Decimal celsius = TemperatureConverter.FahrenheitToCelsius(32);
System.assertEquals(0,celsius);
}
//异常值
@isTest static void testBoilingPoint() {
Decimal celsius = TemperatureConverter.FahrenheitToCelsius(212);
System.assertEquals(100,celsius,'这温度超限啊');
}
//反向测试
@isTest static void testNegativeTemp() {
Decimal celsius = TemperatureConverter.FahrenheitToCelsius(-10);
System.assertEquals(-23.33,celsius);
} }

可以看到,测试类其实至少应该测试正常的业务流程,同时还包括异常/临界/反向三种情况。

默认情况下,Sales force不运行测试类访问正式的ORG数据,除了某些极端情况,比如你要测试报表相关的Apex类,可以使用@isTest(SeeAllData=true)的注解来访问org中的数据,不过一般我们是不建议这样操作的。那么针对这样的情况,也就是需要重复创建一些测试数据的我们怎么做呢,答案是使用Test Utility Classes创建测试数据,也就是创建一个DateFactory类专门提供测试数据,从而避免重复创建数据的问题,也能帮助快速修复一些因为数据不全引起的测试代码报错的问题。

下面看一个Account的trigger示例

 /***********
*
* 测试类最佳实践-示例二
*
*/
trigger AccountDeletion on Account (before delete) {
// 如果关联业务机会则禁止删除Account
for (Account a : [SELECT Id FROM Account
WHERE Id IN (SELECT AccountId FROM Opportunity) AND
Id IN :Trigger.old]) {
Trigger.oldMap.get(a.Id).addError(
'Cannot delete account with related opportunities.');
}
}

准备DataFactory

 @isTest
public class TestDataFactory {
public static List<Account> createAccountsWithOpps(Integer numAccts, Integer numOppsPerAcct) {
List<Account> accts = new List<Account>();
for(Integer i=0;i<numAccts;i++) {//numAccts:创建的Account数量
Account a = new Account(Name='TestAccount' + i);
accts.add(a);
}
insert accts; List<Opportunity> opps = new List<Opportunity>();
for (Integer j=0;j<numAccts;j++) {
Account acct = accts[j];
// 遍历每一个Account,都关联创建一个对应的业务机会
for (Integer k=0;k<numOppsPerAcct;k++) {
opps.add(new Opportunity(Name=acct.Name + ' Opportunity ' + k,
StageName='Prospecting',
CloseDate=System.today().addMonths(1),
AccountId=acct.Id));
}
}
// 插入关联了Accout的业务机会
insert opps;
return accts;
}
}

创建测试类

 @isTest
private class TestAccountDeletion {
@isTest static void TestDeleteAccountWithOneOpportunity() {
// 测试类初始准备测试数据
// 创建一个关联业务机会的Account,并准备删除掉
//Account acct = new Account(Name='Test Account');
//insert acct;
//
// 测试类初始准备测试数据使用DataFactory
// 创建一个Account,关联一个业务机会
Account[] accts = TestDataFactory.createAccountsWithOpps(1,1); // 测试开始
Test.startTest();
Database.DeleteResult result = Database.delete(accts[0], false);
Test.stopTest();
// 校验
// 应该被禁止删除(关联了业务机会)
// 返回的应该是禁止删除的错误提示
System.assert(!result.isSuccess());
System.assert(result.getErrors().size() > 0);
System.assertEquals('不能删除关联业务机会的Account',
result.getErrors()[0].getMessage());
} @isTest static void TestDeleteAccountWithNoOpportunities() {
// 测试初始化
// 创建一个Account,不关联业务机会的
Account[] accts = TestDataFactory.createAccountsWithOpps(1,0); // 测试开始
Test.startTest();
Database.DeleteResult result = Database.delete(accts[0], false);
Test.stopTest();
// 顺利删除
System.assert(result.isSuccess());
} @isTest static void TestDeleteBulkAccountsWithOneOpportunity() {
// 初始化测试数据
// 创建200个Account,创建一个业务机会
Account[] accts = TestDataFactory.createAccountsWithOpps(200,1); // 测试开始
Test.startTest();
Database.DeleteResult[] results = Database.delete(accts, false);
Test.stopTest();
// 校验结果
// 批量删除下,有Account是不能被删除的,数据需要回滚
// 所以我们会得到一个错误的返回值
for(Database.DeleteResult dr : results) {
System.assert(!dr.isSuccess());
System.assert(dr.getErrors().size() > 0);
System.assertEquals('不能删除关联业务机会的Account',
dr.getErrors()[0].getMessage());
}
} @isTest static void TestDeleteBulkAccountsWithNoOpportunities() {
// 初始化
// 创建批量不关联业务机会的数据
Account[] accts = TestDataFactory.createAccountsWithOpps(200,0); // 测试开始
Test.startTest();
Database.DeleteResult[] results = Database.delete(accts, false);
Test.stopTest();
// 顺利批量删除
for(Database.DeleteResult dr : results) {
System.assert(dr.isSuccess());
}
} }

可以看到,我们在完善自己的测试类时,不应该仅仅关注代码的覆盖率,同时也应该注意到对各种正常,异常,临界诸多可能的测试,好的测试能保证代码的质量,尤其需要注意的是经常会被忽略的批量数据处理的问题,在写测试类的时候一般追求覆盖率写出来的测试方法都是模拟用户在界面上的单记录操作,很少会考虑批量数据的测试情况,而在实际的系统使用中是很可能遇到而且容易引起问题的地方。

测试类不应该是Salesforce强制要求的内容,而应该是属于我们写的代码中不可或缺的一部分,希望能重新让你认识到测试类的重要性

如果文中有错误欢迎指正,有问题欢迎留言。

Salesforce 开发整理(一)测试类最佳实践的更多相关文章

  1. Salesforce 开发整理(五)代码开发最佳实践

    在Salesforce项目实施过程中,对项目代码的维护可以说占据极大的精力,无论是因为项目的迭代,还是需求的变更,甚至是项目组成员的变动,都不可避免的需要维护之前的老代码,而事实上,几乎没有任何一个项 ...

  2. [翻译] API测试的最佳实践 - 介绍

    API测试的最佳实践 - 介绍 在上一篇“是什么让API测试很叼”一文中,我们讨论API与其他形式的软件测试的差异.部分是因为API之间的通信压根就没考虑让你能读懂,纯粹是为了方便计算机之间的交互而设 ...

  3. Salesforce 开发整理(八)PDF打印相关

    一:基础设置 Salesforce中的PDF页面本质上还是Visualforce[简称VF]页面,所以只需要给VF页面加上一个属性[renderAs="pdf"] 即可生成一个PD ...

  4. Java Servlet开发的轻量级MVC框架最佳实践

    在Servlet开发的工程实践中,为了减少过多的业务Servlet编写,会采用构建公共Servlet的方式,通过反射来搭建轻量级的MVC框架,从而加快应用开发. 关于Servlet开发的基础知识,请看 ...

  5. 构建高效Presubmit卡点,落地测试左移最佳实践

    樊登有一节课讲的挺有意思,说中国有个组织叫绩效改进协会,专门研究用技控代替人控的事情.其用麦当劳来举例子,他说麦当劳其实招人标准很低,高中文凭就可以,但是培养出来的人,三五年之后,每一个都是大家争抢的 ...

  6. Salesforce 开发整理(十)项目部署总结

    项目部署顺序 全局值集 小组 自定义字段-对象-设置(SF1 紧凑布局要和记录类型在这里要一起部署) 邮件模板-静态资源 角色 工作流-流定义(包含进程生成器) 批准过程 开发部署<Apex类, ...

  7. Salesforce 开发整理(二)报表开发学习

    Salesforce提供了强大的报表功能,支持表格.摘要.矩阵以及结合共四种形式,本文探讨在站在开发的角度要如何理解报表. 一:查询报表基本信息报表在Sales force中是Report对象,基本的 ...

  8. Salesforce 开发整理(九) 开发中使用的一些小技巧汇总[持续更新]

    1.查询一个对象下所有字段 当需要查询一个对象所有字段进行复制或其他操作,可以使用一段拼接的语句来查询 String query = 'select '; for(String fieldApi : ...

  9. Salesforce 开发整理(七)配置审批流

    salesforce提供了比较强大的可配置审批流功能,在系统中翻译为“批准过程”.所以需要配置审批时,选择创建 ——>  工作流和批准 ——> 批准过程,然后选择管理批准过程,选择需要配置 ...

随机推荐

  1. 微信wxid搜索用户不存在,怎么加好友?

    点击上方↑↑↑蓝字[协议分析与还原]关注我们 " 根据wxid微信号找到用户的方法及周边资料大全." 最近经常会收到好友请求的消息提醒,但却不是通过搜索好友和群聊来添加的,因此研究 ...

  2. RAC环境下修改字符集

    跟单实例多少有点区别ORACLE 11g RAC 两节点第一步 查看字符集PRIMARY-SYS@mydb2>select userenv('language') from dual; USER ...

  3. MySQL语句使用。

    目录 MySQL的DDL.DML.DQL语句和单表增.删.改.查 实验准备: 实验开始: DDL语句 DML语句 DQL语句 单表操作的分组统计 MySQL的DDL.DML.DQL语句和单表增.删.改 ...

  4. August 18th, 2019. Week 34th, Sunday

    Fear doesn't shut you down, it wakes you up. 恐惧不会消磨你的意志,它能激发你的潜能. We all know that fear is powerful, ...

  5. 图片转换成base64

    let bgcImage = 'http://192.168.0.83:9080/files/4a9c3056-9b9b-4b41-b8e2-fd9f27023c41.jpg' let image = ...

  6. 关于String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

    关于 String path = request.getContextPath(); String basePath = request.getScheme()+"://"+req ...

  7. java之等待唤醒机制(线程之间的通信)

    线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同.比如:线程A用来生成包子的,线程B用来吃包子的,包子可以理解为同一资源,线程A与线程B处理的动作,一个是生产,一个是消 ...

  8. Exe4j 打包: this executable was created with an evaluation version of exe4j

    异常 this executable was created with an evaluation version of exe4j   异常.png 问题原因 当前打包使用exe4j未授权 解决方法 ...

  9. docker 指定版本rpm包安装

    1.docker rpm包下载地址 # https://download.docker.com/linux/centos/7/x86_64/stable/Packages/ 2.下载rpm包 # wg ...

  10. 解决“var/log/sysstat/sa21: 没有那个文件或目录 请检查是否允许数据收集”

    想使用sar查看一些系统的一些活动信息,发现报错.记录一下 使用apt install sysstat后第一次 报错 /var/log/sysstat/sa21: 没有那个文件或目录 请检查是否允许数 ...