Salesforce 数据结构(2)

学习目标

完成本单元后,您将能够:

  • 定义不同类型的对象关系及其典型用例。
  • 创建或修改查找关系。
  • 创建或修改主从关系。

什么是对象关系?

现在我们对对象和字段感到满意了,现在是时候把对象关系带到下一个层次了。对象关系是将两个对象连接在一起的特殊字段类型。

让我们来考虑一个像Account这样的标准对象。如果销售代表打开一个帐户,他们可能已经与该帐户的公司中的几个人交谈。他们可能已经与高管或IT经理建立了联系,并将这些联系人的信息存储在Salesforce中。

那么,Account对象和Contact对象之间应该有一个关系是有意义的。还有!

当您查看Salesforce中的帐户记录时,可以看到“相关”选项卡上的联系人部分。您还可以看到有一个按钮,可以让您快速添加联系人到一个帐户。

An account record with two related contacts.

Account to Contact关系是Salesforce中标准关系的一个示例。但是就像对象和字段一样,你也可以建立自定义关系。在最后一个单元中,您创建了两个对象:Property和Offer。如果在家中提供的所有优惠都显示在Salesforce的记录上,这不是很好吗?

在我们这样做之前,先谈谈您可以在Salesforce中创建的各种关系。

对象关系的广泛世界

有两种主要类型的对象关系:查找和主要细节。

查找关系

在上面我们的Account to Contact例子中,两个对象之间的关系是查找关系。查找关系基本上将两个对象链接在一起,以便您可以从另一个对象上的相关项目中“查找”一个对象。

查找关系可以是一对一或一对多。客户到联系人关系是一对多的,因为一个客户可以有许多相关的联系人。对于我们的DreamHouse场景,您可以在Property对象和Home Seller对象之间创建一对一的关系。

主从关系

尽管查找关系相当随意,但主从关系有点紧密。在这种关系中,一个对象是主人,另一个是细节。主对象控制着细节对象的某些行为,比如谁可以查看细节的数据。

举例来说,假设一个物业的业主想把他们的房子赶出市场。 DreamHouse不希望保留任何提供该属性的优惠。通过Property和Offer之间的主从关系,您可以从系统中删除该属性及其所有关联的商品。

A property with several related offers.

更多的关系

就像在现实生活中一样,关系也很复杂。这里有更多的信息可以帮助您区分查找和主从关系。

通常情况下,只有在某些情况下才会关联对象时才使用查找关系。有时联系人与特定的帐户关联,但有时只是联系人。查找关系中的对象通常作为独立对象工作,并在用户界面中拥有自己的选项卡。

在主从关系中,详细对象不能作为独立工作。这是高度依赖于主人。事实上,如果主对象上的记录被删除,那么所有相关的详细记录也被删除。在创建主从关系时,总是在详细对象上创建关系字段。

最后,你可以运行第三种关系类型,称为等级关系。分层关系是一种特殊的查找关系。两者之间的主要区别在于层次关系仅在用户对象上可用。您可以使用它们来创建用户之间的管理链。

当您开始添加对象之间的关系时,请记住,您正在增加数据模型的复杂性。这不是一件坏事,但是当你做更改和删除对象,记录或者字段的时候要格外小心。查看资源部分了解关于关系行为的更多信息。

创建查找关系

我们准备好与D’Angelo一起为DreamHouse应用程序建立一些关系。假设DreamHouse希望能够跟踪用户在自己网站上最喜欢的属性。这个功能可以帮助DreamHouse的房地产经纪人接触到潜在的购房者。

首先,创建一个自定义对象,称为具有自动编号名称字段的收藏夹。如果您需要提醒如何创建对象,请检查以前的单位。

我们将在Favorite对象上创建两个自定义关系字段。首先,我们创建一个查找关系,列出收藏属性的用户。

  1. 从安装程序中,转到 Object Manager | Favorite.
  2. 在边栏上,点击 Fields & Relationships.
  3. 点击 New.
  4. 选择 Lookup Relationship 然后单击 Next.
  5. 对于相关,请选择联系人。 为了DreamHouse的目的,联系人代表潜在的购房者。
  6. 点击 Next.
  7. 对于字段名称,请输入联系人并单击 Next.
  8. 单击 NextNext, 和 Save & New.

创建主从关系

现在,我们要创建第二个关系字段。 我们想要一个主从关系,其中属性是主,最喜欢的是细节。

  1. 选择 Master-Detail Relationship 然后单击 Next.
  2. 对于相关,选择 Property.
  3. 点击 Next.
  4. 对于字段名称,输入属性,然后单击 Next.
  5. 点击 NextNext, 和 Save.

做得好! 我们最喜欢的对象是全部设置的。 现在,如果您查看“财产”或“联系人”记录,则会看到相关选项卡中有“收藏夹”部分。

A property record with one favorite.

Salesforce 数据结构(1)

学习目标

完成本单元后,您将能够:

  • 描述在Salesforce平台上使用对象的好处。
  • 解释标准对象和自定义对象之间的区别。
  • 列出对象可以具有的自定义字段的类型。

对象概述

DreamHouse是一家房地产公司,为客户提供购买房屋和在线联系房地产经纪人的途径。 DreamHouse经纪人使用Salesforce的一些标准功能(如联系人和线索)来跟踪购房者。

但是在售房方面,还有很多事情要跟踪。例如,Salesforce不包含跟踪属性的标准方法。 DreamHouse如何知道他们有哪些房屋可供出售,或者每个房屋的价格是多少?

幸运的是,他们的Salesforce管理员D’Angelo知道Salesforce平台提供了一个解决方案。我们将与D’Angelo一起工作,看看他正在建造什么。

我们从数据模型开始。数据模型或多或少是这样的。这是以一种对人类有意义的方式建模数据库表的方法。

如果您不熟悉数据库,请考虑将数据存储在电子表格中。例如,D’Angelo可以使用电子表格来追踪所有DreamHouse的属性。列可以存储地址,成本和其他重要属性。行可以存储DreamHouse销售的每个房产的这些信息。数据库表的设置方式与此类似。

A spreadsheet that stores property information.

但是查看表格中的数据对于人类来说并不理想。这就是数据模型的来源。

在Salesforce中,我们将数据库表视为对象,我们将列视为字段,将行视为记录。因此,我们不是使用帐户电子表格或表格,而是使用帐户对象的字段和一堆相同的结构化记录。

A property record with the same information as the table.

当我们谈论数据模型时,我们正在讨论应用程序中的对象和字段的集合。让我们进一步了解对象和领域,以便开始构建自己的数据模型。

了解对象

Salesforce支持几种不同类型的对象。有标准对象,自定义对象,外部对象,平台事件和BigObjects。在这个模块中,我们关注两种最常见的对象类型:标准和自定义。

标准对象 是Salesforce附带的对象。通常的业务对象,如客户,联系人,潜在客户和机会都是标准对象。

自定义对象是您创建的对象,用于存储特定于您的公司或行业的信息。对于梦幻屋,D’Angelo希望建立一个自定义的Property对象来存储他的公司正在销售的房屋的信息。

对象是您的信息的容器,但它们也给你特殊的功能。例如,当您创建自定义对象时,平台将自动构建用户界面的页面布局。

创建一个自定义对象

让我们和D’Angelo一起来看看他是如何构建Property对象的。我们稍后需要这个对象,所以不要跳过这些步骤!

  1. 滚动到此页面的底部。
  2. 点击启动旁边的箭头,然后选择 Create a Trailhead Playground. 不要跳过这一步!您需要为这个模块使用一个清新干净的Trailhead游乐场。
  3. 一旦你的TP被创建(这需要一分钟!),按 Launch.
  4. 点击 The setup gear. 安装设备。在页面顶部并启动设置。
  5. 单击 Object Manager 选项卡.
  6. 点击 Create | Custom Object 在右上角。
  7. 对于标签,请输入Property. 请注意,对象名称和记录名称字段自动填充。 
  8. F对于复数标签,输入 Properties.
  9. 保存此自定义对象后,选中 Launch New Custom Tab Wizard after saving this custom object.
  10. 将其余的值保留为默认值,然后单击 Save.
  11. 选择所需的标签样式,然后单击 NextNext, and Save.

做得好!你刚创建你的第一个自定义对象。现在,我们来讨论一下为这个对象添加字段。

了解领域

每个标准和自定义对象都有附加的字段。让我们熟悉不同类型的领域。

字段类型 是什么? 我能举个例子吗?
身分 每个记录自动生成一个15个字符的区分大小写的字段。 您可以在其URL中找到记录的ID。 帐户ID看起来像0015000000Gv7qJ。
系统 提供有关系统记录信息的只读字段,例如创建记录或上次更改记录时。 CreatedDateLastModifiedById, 和LastModifiedDate.
名称 所有记录都需要名称,以便可以区分它们。 您可以使用每次创建记录时自动递增的文本名称或自动编号的名称。 联系人的名字可以是Julie Bean。 支持案例的名称可以是CA-1024。
自定义 在标准或自定义对象上创建的字段称为自定义字段。 您可以在联系人对象上创建自定义字段来存储联系人的生日。

身份,系统和名称字段是Salesforce中每个对象的标准。每个标准对象还带有一组预制的标准字段。您可以通过添加自定义字段来自定义标准对象,并且可以将自定义字段添加到自定义对象。

每个字段都有一个数据类型。数据类型表示字段存储的是什么类型的信息。 Salesforce支持一堆不同的数据类型,但这里有几个你会遇到。

  • 复选框—对于简单的“是”或“否”字段,复选框字段是您想要的。
  • 日期或日期时间—这些字段类型表示日期或日期/时间组合,如生日或销售里程碑。
  • 公式—这个特殊字段类型拥有一个基于你写的公式自动计算的值。例如,D’Angelo可以编写一个公式字段,自动计算房地产经纪人的房屋销售佣金。

再次,有相当多的领域类型,但其中大部分是相当不言自明的。这里重要的一点是,您想要考虑创建自定义字段时要存储什么类型的数据。

创建一个自定义字段

我们刚创建的Property对象是相当简单的。让我们添加一些自定义字段。回到你的Trailhead游乐场。

  1. 从安装程序中,转到 Object Manager | Property.
  2. 在边栏中,点击 Fields & Relationships. 注意那里已经有一些字段了。有一个名称字段和我们之前谈到的一些系统字段。
  3. 点击 New 右上角的
  4. 对于数据类型,选择Currency.
  5. 点击 Next.
  6. 填写以下内容:
    1. 字段标签Price
    2. 描述The listed sale price of the home.
  7. 选中 Required.
  8. 点击 NextNext 再次点击 Save.

您将在Property字段列表中看到新的Price字段。在“字段名称”列中,注意它说Price__c。 “__c”部分是一个简单的方法来告诉一个特定的字段是一个自定义字段。

创建一个记录

让我们创建一个财产记录,看看你做了什么。

  1. 从应用程序启动器应用 The App Launcher icon. 在页面顶部, 选择Sales.
  2. 单击 Properties 选项卡导航栏中的.如果您没有看到它,请查看More 下拉菜单
  3. 点击顶部的New.
  4. 输入属性的名称和价格,然后单击 Save.

真棒!你会看到这样的东西:

The record you just created.

定制负责任

虽然添加和自定义对象似乎很容易,但请记住,引擎盖下面发生的事情在技术上是复杂的。在开始定制自己的组织时,请记住一些最佳实践。

仔细考虑名字. 一旦你开始创建一堆对象,可能会给他们一些“懒惰”的名字。例如,如果D’Angelo创建另一个自定义对象来跟踪共管公寓,他可能会试图将其命名为“Property2”而不是“Condominium”。这是您组织中混乱的秘诀。给你的对象和领域描述性的,独特的名称,以提高清晰度。

帮助你的用户 即使仔细命名,您的用户可能并不总是清楚特定对象或字段的用途。包含您的自定义对象和字段的说明。对于专业或复杂的自定义,请使用帮助文字提供更多详细信息。

必要时需要字段 有时候,当用户在某个对象上创建一个记录时,你需要强制用户填写一个字段。每个物业都需要一个价格,对吧?使重要的领域,以避免不完整的数据。

Salesforce 基础(5)

学习目标

完成本单元后,您将能够:

  • 开发您自己的AppExchange策略。
  • 从AppExchange安装应用程序。

什么是AppExchange?

你可能对应用商店的想法感到满意。无论您是在手机,平板电脑,计算机还是其他设备上下载应用程序,都必须下载并安装应用程序才能充分利用您的技术。

Salesforce也是一样。早些时候,我们提到了企业生态系统。 Salesforce拥有一个使用Salesforce平台灵活性的合作伙伴社区,以构建令人惊叹的应用程序以及任何人都可以使用的解决方案。这些产品可以在AppExchange上安装(有些是免费的,有些是有偿的)。

The AppExchange homepage.


成功策略

D’Angelo的DreamHouse应用程序是公司房地产经纪商中的一个炽热的成功。但如果我们现实的话,D’Angelo只是一个人。他一天只有这么多时间才能为他的同事开发新的应用程序。

幸运的是,AppExchange有很多应用程序,D’Angelo可以下载,帮助DreamHouse管理从工资单到旅行批准到与Evernote和MailChimp等其他工具的整合。

AppExchange提供的可能性是令人兴奋的,但在开始下载每个应用程序之前,您需要制定一个策略。坚实的AppExchange策略有助于确保您获得最高价值的应用程序,而无需重复功能或投资于您不需要的东西。

按照以下步骤开发一个好的AppExchange策略。

  1. 确定使用或计划使用Salesforce的部门。这是你的主要利益相关者。
  2. 研究AppExchange上最适合您的利益相关者需求的可用内容。与部门负责人讨论商业案例,以确定确切的需求。这里有一些很好的问题要问:
    1. 你想解决什么业务问题?
    2. 你现在主要的痛点是什么?
    3. 有多少用户需要这个应用程序?
    4. 你的预算是多少?
    5. 你的时间线是什么?

    这些问题可帮助您识别最适合每个部门或业务案例的应用程序。

  3. 当您找到一款您认为符合您需求的应用程序时,请在测试环境(如免费的开发版或沙箱)中下载该应用程序。确保您正在安装的应用程序不会干扰您已安装的任何其他应用程序或您所做的自定义设置。

    注意

    沙箱是单独环境中组织的副本。他们用于开发和测试。请参阅沙盒概述。

  4. 如果您在多个应用程序中进行选择,请花一些时间评估您测试的内容。确定是否有功能差距或不需要的功能。如果有必要,请邀请您的利益相关者演示应用程序并提供反馈。
  5. 你准备好了!您将在生产环境中安装和部署您的应用程序。确保让用户了解发生了什么变化,并根据需要提供培训和文档。

安装你的第一个应用

虽然AppExchange类似于传统应用程序商店,您可以在手机或平板电脑上找到,但务必记住,您的Salesforce组织是一个复杂的环境。你不能只安装一个应用程序,因为它有一个很酷的标志或令人信服的标语。

那么安装应用程序的正确方法是什么?我们会告诉你的!

假设您在AppExchange上找到了这个优秀的应用程序,它为您提供了一组适合您的组织的仪表板。

The AppExchange Dashboard Pack's AppeExchange page.
要安装该应用程序,请单击立即获取。该按钮将带您到安装向导,引导您完成这些步骤。以下是在安装过程中需要回答的两个关键问题:

Q: 我在哪里安装应用程序,生产或沙箱?
A: 一般来说,最好先在沙盒或开发版组织等非生产环境中安装应用程序。首先测试应用程序可以帮助您避免生产中的对象名称冲突。
Q: 我是否仅向应用管理员,所有用户或特定配置文件授予应用权限?
A: 这取决于应用程序的用途。如果要限制对特定用户组的访问权限,请计划在安装应用程序之前修改这些用户配置文件。

我的应用去哪了?

恭喜!您已安装您的第一个应用程序。现在,只要你能找到它…

应用程序使用称为包的东西安装。要找到这个包:

  1. 从“设置”中,搜索并选择“快速查找”框中的“安装的软件包”。
  2. 点击你安装的软件包的名称。这将是从AppExchange下载页面相同的名称。
  3. 单击查看组件查看有关该软件包的更多信息。 “程序包详细信息”页面显示了程序包中的所有组件,包括自定义字段,自定义对象和Apex类。这些信息可帮助您确定自己的自定义设置中是否存在任何冲突。

一些最后的想法

当您开始探索AppExchange时,请务必查看由Salesforce Labs提供的免费应用程序。 除了免费的Salesforce实验室应用程序之外,它们是开源的。 您可以根据需要定制它们,并在引擎盖下窥视,看看它们是如何工作的。 这是学习更多关于平台如何工作的好方法。

说到学习更多,这个模块为您深入了解Salesforce平台奠定了坚实的基础。 查看下面的资源,了解您旅程中的一些可能的后续步骤。 快乐的小道!

Salesforce 基础(4)

学习目标

完成本单元后,您将能够:

  • 找到设置并确定其关键元素。
  • 确定用于自定义组织的重要菜单。
  • 使用快速查找来访问菜单项。

安装程序:您的新工作主页

早些时候,我们提到您在Salesforce管理员工作期间将花费大量的时间在安装程序上。我们不是在开玩笑。安装程序是您的一站式服务,用于自定义,配置和支持您的组织。

由于您可以在“设置”区域中执行如此多的操作,因此在浏览时很重要。有几种方法来处理它。当你了解什么是你可以得到的东西时,你会更容易找到你需要的东西。

您可以从Salesforce组织的任何页面进入安装程序。从屏幕顶部的齿轮菜单 (The gear icon to open Setup.), 单击Setup设置。让我们熟悉安装区域。

The standard view of Setup's homepage.
  1. 对象管理器: 对象管理器是您可以查看和定制组织中的标准和自定义对象的地方。
  2. 设置菜单: 通过该菜单,您可以快速链接到一组页面,让您可以从管理用户到修改安全设置。
  3. 主窗口: 我们向您展示了设置主页,但是您可以在这里看到您正在尝试的任何内容。

设置菜单是最难以浏览的部分,因为有许多不同的页面可以访问。有两种方法可以到达你想去的地方。如果您已经知道在哪里寻找,请展开相应的菜单并选择所需的页面。如果您不确定在哪里寻找,请使用“快速查找”框进行搜索。比方说,你想管理你的用户权限集。如果您碰巧知道权限集在“管理”下的“用户”菜单中,只需打开该菜单并单击权限集。否则,请在“快速查找”框中输入权限集。

获取舒适的设置菜单

“设置”菜单中有三个主要类别:管理,平台工具和设置。让我们来看看有什么可用的。

  • 管理: 管理类别是您管理用户和数据的地方。您可以执行添加用户,更改权限,导入和导出数据以及创建电子邮件模板等操作。

  • 平台工具: 您在平台工具中执行大部分自定义工作。您可以查看和管理您的数据模型,创建应用程序,修改用户界面以及将新功能部署到您的用户。如果您决定尝试编程开发,Platform Tools也是您管理代码的地方。
  • 设置: 最后,设置是您管理公司信息和组织安全的地方。您可以执行诸如添加营业时间,更改您的语言环境以及查看您的组织历史记录等内容。

当然,这些只是您可以在“设置”菜单中访问的一部分页面。为了让您的脚步开始,下面列出了我们要了解的五大安装页面。

# 项目 为什么这是一个必须看到
1 公司信息
  • 一览您的组织结构
  • 找到您的组织ID
  • 查看您的许可信息
  • 监控重要的限制,如数据和文件使用情况
2 用户
  • 重置密码
  • 创建新用户并停用或冻结现有用户
  • 查看有关您的用户的信息
3 简介
  • 管理谁可以看到用户配置文件
  • 创建定制配置文件
4 查看设置审计跟踪
  • 查看您组织中6个月的变更历史记录
  • 找出谁做了什么改变,什么时候做
  • 解决组织问题的工具
5 登录历史
  • 查看6个月的登录历史记录
  • 查看日期,时间,用户,IP地址以及更多登录数据
  • 用于安全跟踪和采用监视

Salesforce 基础(3)

学习目标

完成本单元后,您将能够:

  • 定义与Salesforce体系结构相关的关键术语。
  • 查找与信任有关的信息。
  • 解释至少一个Salesforce API的用例。

什么是Salesforce架构?

现在您知道您可以使用Salesforce为您的客户,员工和合作伙伴提供高度定制的体验。你可以在不写很多(或任何)代码的情况下做到,而且你可以快速完成。

Salesforce有什么特别之处?这一切都始于我们的建筑。

在为了避免了解这个看起来很枯燥的话题而疯狂地尝试关闭这个窗口之前,请坐下来。了解Salesforce体系结构非常有趣,理解它使得使用该平台变得更加容易。

当您考虑Salesforce体系结构时,想象一系列彼此重叠的图层。有时把蛋糕想象成蛋糕是有好处的,因为蛋糕很好吃,而且使一切变得更好。

A diagram outlining Salesforce architecture.

这里有很多东西需要解压缩,但是让我们把重点放在最重要的一点上。

  • Salesforce是一家云端公司。我们提供的一切都在可信的多租户云中。
  • Salesforce平台是我们服务的基础。它由元数据驱动,由不同的部分组成,如数据服务,人工智能和强大的开发API。
  • 我们所有的应用程序都位于平台之上。 Sales Cloud和Marketing Cloud等预构建产品以及您使用该平台构建的应用程序具有一致,强大的功能。
  • 一切都是整合的。我们的平台技术,如爱因斯坦预测智能和Lightning框架开发,都建立在我们所提供的一切和您所建立的一切。

这里有几个术语对于您来说是非常重要的:信任,多租户,元数据和API。

为什么信任云?

在Salesforce,信任是我们的首要任务。您不仅可以将敏感数据保存在您的组织中,还可以在我们的平台上构建对公司成功至关重要的功能。我们承担保证数据和功能安全的责任并不是我们轻视的,这就是为什么我们始终对我们的服务保持透明。

我们的信任网站trust.salesforce.com是一个重要的资源。您可以使用它来查看性能数据并获取有关我们如何保护您的数据的更多信息。它还会显示您将执行的任何计划内维护,这可能会影响您对Salesforce的访问。

共享关注多租户云

到目前为止,我们一直在谈论很多房子。但是,Salesforce的设立更像一个公寓楼。你的公司在云中有自己的空间,但你有各种各样的邻居,从母子店到跨国公司。

An apartment building with dedicated space but shared resources.

这个想法是多租户的。多餐厅是让你在宴会上变得聪明的一个很好的词,但是真正意义上的是你要共享资源。 Salesforce为多租户云中的所有客户提供了一套核心服务。无论您的业务规模如何,您都可以使用相同的计算能力,数据存储和核心功能。

信任和多租户齐头并进。尽管您与其他公司共享空间,但您可以信任Salesforce以保护您的数据安全。您也可以相信,您将获得最新且最强大的功能,并且每年可以进行三次自动无缝升级。由于Salesforce是一项云服务,您不必安装新功能或担心硬件问题。所有这一切都是可能的,因为多租户。

元数据的魔力

简而言之,元数据是关于数据的数据。等待。这根本不简单。当我们说关于数据的数据时,我们真的在谈论你的Salesforce组织结构。

让我们来考虑像Property这样的对象。当我们的DreamHouse的朋友使用Salesforce时,他们输入并查看有关属性的数据。例如,一个物业可以位于波士顿,花费$ 500,000,并有3间卧室。

现在,想象一下你剥离了所有的具体数据。你还剩什么?您将留下属性对象及其所有字段,如地址,价格和卧室数量。您还可以拥有页面布局,安全设置以及您所做的任何其他自定义设置。

元数据中的所有这些标准和自定义配置,功能和代码都是元数据。您可以在平台上如此快速地移动的部分原因是,Salesforce知道如何在创建元数据后立即存储和提供元数据。

所有关于该API

从根本上讲,API允许不同的软件相互连接并交换信息。

如果这听起来很抽象,那么立即看看你正在使用的计算机。你可能会找到一系列支持不同类型连接的各种形状和大小的端口。这些就像API的硬件版本。您不必知道USB端口如何工作。所有你必须明白的是,当你的手机插入USB端口时,它将信息传递到你的电脑。

API是相似的。不知道细节,你可以连接你的应用程序与其他应用程序或软件系统。基础技术负责信息在整个系统中传递的具体细节。

那么这与Salesforce有什么关系呢?

早些时候,我们谈到了数据库。添加自定义对象或字段时,平台会自动创建一个API名称,作为组织和数据库之间的访问点。 Salesforce使用该API名称来检索要查找的元数据和数据。

例如,我们可以在一堆地方使用联系人的姓名字段,如Salesforce移动应用程序,自定义页面甚至电子邮件模板。这些都是可能的,因为API的名字。

An email template in Salesforce using the API name of a contact and property.

API功能的核心是所有数据和元数据都启用了API。这看起来可能不是什么大问题,但API给了Salesforce很大的灵活性。它可以让您超越商业软件的正常理念,为您的公司打造独特而有创意的解决方案。看看这个视频的例子,你可以走多远。

虽然您可以将您的Salesforce数据与Minecraft集成在一起真的很棒,但API也有许多实际的应用程序。每次使用Salesforce时,无论您是使用标准功能还是构建自定义应用程序,都需要与API进行交互。

Salesforce 基础(2)

学习目标

完成本单元后,您将能够:

  • 描述该平台的示例用例。
  • 发现跨多个部门使用平台的资源。

高影响力,低努力

该平台可以帮助您快速移动。部分速度来自于用更简化的流程替换您以前用手做的任务。所以让我们暂停一下,谈谈Salesforce平台可以加速您的业务的一些方法。

当你在平台上学习时,你想要解决的第一件事是那些影响很大但易于实现的项目。虽然这听起来很理想,但这个平台给了你很多机会,用最小的努力做出重大的改变。

我们来看一个来自DreamHouse的例子。米歇尔和她的经纪人经常使用电子邮件来讨论特定的属性。有时,米歇尔参与讨论同一财产的多个线索,可能会引起混淆。所有的电子邮件之间,细节迷失。当经纪人忽视细节时,他们可能会错过出售或者犯下影响买方的错误。

Michelle looking overwhelmed by emails.

那么Salesforce平台如何帮助解决这个问题呢?好吧,对于DreamHouse Realty,D’Angelo创建了一个自定义Property对象,我们在最后一个单元中看到。每次创建自定义对象时,都会自动获取一个名为Chatter提要跟踪的内容。 Chatter Feed跟踪为多人提供了在特定记录上进行评论和协作的方法。讨论和决定存储在记录中,以便每个人都能及时了解重要的决策。现在,米歇尔和她的经纪人不必再用电子邮件来讨论一个特定的财产。

An example of a Chatter post to collaborate on a specific property.

通过创建一个自定义对象,您完全可以改变您的组织如何协作。高影响力,低努力。当您开始搭建平台时,请留意以下流程:

  • 重邮件协作
  • 依靠电子表格
  • 共享本地文件
  • 时间密集,重复的手动步骤
  • 只对少数部门有影响(当你还在学习的时候,要尽量减少利益相关者的数量)

具有这些特质的流程是Salesforce平台早期项目的绝佳选择。

平台的其他用途

在我们的DreamHouse故事中,我们使用Salesforce帮助房地产经纪人更好地销售房屋。但是,您可以自定义平台来帮助完成许多其他业务任务,而不仅仅是销售部门。让我们看看您可以在Salesforce上构建的其他两种方法。

人力资源可以使用平台

在DreamHouse HR部门工作的Julian正处于危机之中。他有数百个应用程序进入数十个职位空缺。一旦申请人被聘用,Julian必须建立培训并提交硬件请求。所有这些活动都会产生大量的数据,Julian正在努力管理这一切。

D’Angelo来救援!

使用Salesforce平台,D’Angelo可以创建一个自定义应用程序,帮助DreamHouse的HR员工简化和自动化招聘和入职流程。这里是一些自定义应用程序可以做的事情。

  • 列出职位空缺。
  • 存储每个职位空缺的申请人。
  • 向招聘经理发送自动提醒。
  • 存储方向和培训计划。
  • 管理设备订单。
  • 跟踪员工的休假时间。

与平台上构建的任何应用程序一样,D’Angelo创建的HR应用程序可用于Salesforce移动应用程序。这样一来,人力资源代表可以管理申请人和新员工,不管他们是在办公室还是在招聘会上。凉!Cool!

IT可以使用该平台

在IT方面,里贾纳也感受到了燃烧。她每分钟都会得到一百万张IT票,每个人的问题似乎都是紧急的。谁可以请求帮助这个门票的洪流?

你猜到了。她友好的邻居Salesforce管理员,D’Angelo。

当您在与您的CRM相同的位置构建IT票务系统时,您会获得很多好处。你所有的用户和他们的信息已经在那里。您可以跟踪每个用户的案例并促进IT与员工之间的协作。以下是使用Salesforce平台简化IT的一些其他方法:

  • 创建报告和仪表板来聚合和分析请求。
  • 请求收到,完成或更新时发送确认电子邮件。
  • 排队传入的请求。
  • 为员工请求创建自定义表单,并为常见问题创建知识库。
  • 跟踪员工硬件资产。

通过简化IT流程,用户更加快乐,IT部门有更多时间来构建基础架构,而不是维护一个单独的系统。

您可以使用该平台

到目前为止,你可能正在为自己的项目获得一些想法。以下是针对不同部门的一些用例。

对于在…工作的员工… 自定义平台…
金融
  • 预算管理
  • 合同管理
  • 价钱
产品
  • 保修管理
  • 预生产测试
  • 产品理念和创新
供应链
  • 采购
  • 供应商管理
  • 后勤
行动
  • 资产和设施管理
  • 兼并和收购支持
  • 业务敏捷性

如果您希望获得更多灵感,请查看Salesforce客户在资源部分中使用该平台的一些方法。

Salesforce 基础(1)

学习目标

完成本单元后,您将能够:

  • 定义Salesforce平台。
  • 描述DreamHouse场景。
  • 创建一个Trailhead游乐场。
  • 解释声明式和程序式开发之间的区别。

Salesforce快速入门

您可能认为Salesforce只是一个CRM。它存储您的客户数据,为您提供培训潜在客户的流程,并提供与您合作的人员进行协作的方法。它能完成所有这些事情。但是说Salesforce是“只是一个CRM”,就像说房子只是一个厨房。还有比这更多的东西。

Salesforce提供了许多标准功能,或者可用于运行业务的开箱即用产品和功能。以下是企业想要使用Salesforce的一些常见事项以及我们为您提供的支持这些活动的功能。

你需要: 所以我们给你:
销售给潜在客户和客户 潜在客户和机会来管理销售
售后帮助客户 客户参与的案例和社区
在旅途中工作 可定制的Salesforce移动应用程序
与同事,合作伙伴和客户合作 Chatter和社区连接你的公司
向您的观众展示市场 营销云来管理您的客户旅程

根据你的公司购买什么,你可以得到这些功能,而不是一个手指。但是你几乎可以把这些功能想象成一个房地产经纪人炫耀的样板房。你当然可以住在那里,但它不会是你的家。它不会有你的艺术在墙上或那个不寻常的外套架子,你的阿姨蒂尔达给你作为乔迁礼物。

这就是Salesforce平台的用武之地。有了这个平台,您可以自定义和构建让您的公司独一无二的东西。当你有一个独特的商业应用程序,每个人都更成功。

Salesforce的故事

在整个Trailhead中,您将以不同的方式介绍许多使用Salesforce的公司和角色。我们来见一些球员。

These four companies appear throughout Trailhead to help you learn about our services.
  1. 云踢—这家定制运动鞋公司正在制鞋行业掀起波澜。他们使用Salesforce管理销售,并帮助简化复杂的订单创建和执行流程。
  2. 大熊之光—在可再生能源的前沿,大熊之光需要商业软件,不会背离开创性的技术。他们使用Salesforce管理全国的销售和客户服务。
  3. 多云咨询 —作为业内最好的云咨询公司之一,多云知道CRM。他们使用Salesforce来管理现有的和潜在的客户,他们一直在寻找创新的Salesforce服务的新方法。
  4. DreamHouse Realty— 以其新颖的房地产方式而闻名,DreamHouse使用Salesforce连接员工,提高住宅销售的效率。

我们正在挖掘这个房子的主题,所以让我们看看DreamHouse Realty,开始我们的第一个模块。我们将使用DreamHouse的Salesforce实施来解释Salesforce平台的一些基本术语,概念和功能。

让我们多了解DreamHouse。

Michelle是DreamHouse的主要房地产经纪人。她通过DreamHouse的网络和移动应用程序发现了许多潜在的购房者。通过这些应用程序,客户可以浏览可用的房屋,并创建他们感兴趣的物业的最爱列表。他们也可以直接联系米歇尔或其他经纪人设置放映。

Michelle, the lead broker at DreamHouse.

D’Angelo是DreamHouse的Salesforce管理员。使用Salesforce平台,他正在构建一套自定义功能来支持Michelle及其团队。米歇尔可以使用这个自定义功能来编辑和查看有关她卖的物业的信息,以及跟踪她的潜在买家。

D'Angelo, the Salesforce Admin at DreamHouse.

请记住,Salesforce具有用于跟踪帐户,联系人和潜在客户等常见销售对象的标准功能。但是DreamHouse是一家房地产公司,所以它的行业和商业模式都有特定的需求。在本模块中,我们将与D’Angelo合作,了解Salesforce平台如何满足这些需求。

了解我们的条款

也许你在最后一段中注意到一个奇怪的词:对象。对象是您了解Salesforce时学到的许多重要术语之一。

首先,了解Salesforce上下文中的数据库非常重要。当我们谈论数据库时,想想一个巨大的电子表格。当您将信息放入Salesforce时,它将被存储在数据库中,以便稍后再次访问它。它存储在一个非常特定的方式,所以你总是访问你需要的信息。

我们来看一下DreamHouse应用中的一个页面,以定义它的一些重要元素以及它们与数据库的关系。

A labeled property record.
  1. Salesforce中的应用程序是一组支持业务流程的对象,字段和其他功能。您可以看到您正在使用的应用程序,并使用应用程序启动器 (App Launcher icon)在应用程序之间切换。.
  2. 对象是Salesforce数据库中用于存储特定类型信息的表。有像客户和联系人这样的标准对象和图形中看到的像Property对象这样的自定义对象。
  3. 记录是对象数据库表中的行。记录是与对象关联的实际数据。在这里,查尔斯街211号的房产是一个纪录。
  4. 字段是对象数据库表中的列。标准和自定义对象都有字段。在我们的Property对象中,我们有像Address和Price这样的字段。

组织中另一个难以捕捉的重要术语是org。组织是组织的简称,它指的是Salesforce的特定实例。这里的图片取自DreamHouse的组织。你的公司可以有一个或多个组织。

这是很多新的东西来解决。如果你不能立刻得到它,不要担心。在您继续了解Salesforce的过程中,术语将自然而然地出现。

你的第一个Trailhead游乐场

Trailhead Playground(TP)组织是一个安全的环境,您可以在将自己学习的技能练习到实际工作之前练习。 TP配备了测试应用程序开发版本所需的所有标准应用程序构建和定制工具。如果您听说过开发版(DE)组织,则TP是特殊类型的DE。

当您注册Trailhead时,我们会自动为您创建一个TP。所以,如果你还没有注册,现在是一个很好的时机。如果您已经登录,请滚动到该页面的底部,然后点击“启动”打开您的TP。

TP组织是免费的,一次最多可以有10个组织。要创建一个,请执行任何操作上的挑战,单击启动旁边的向下箭头,然后选择创建一个Trailhead游乐场..如果你打你最大或想要管理你的TP,你可以查看和删除你的Trailhead配置文件。如果您需要使用您的TP的用户名和密码,可以使用这里的说明访问它们。

继续前进,启动你的TP,这样我们就可以开始把我们的手弄脏了。

自定义Salesforce平台

您已经知道您可以使用Salesforce平台来开发特定于您的业务的自定义对象和功能。你可能不知道的是,你可以在不写一行代码的情况下完成大部分的开发工作。

无代码开发被称为声明式开发。通过声明式开发,您可以使用表单和拖放工具来执行强大的自定义任务。该平台还提供程序开发,使用Lightning组件,Apex代码和Visualforce页面等。但是如果你不是程序员,你仍然可以在平台上构建一些令人惊叹的东西。

我们从小开始。米歇尔希望能够迅速表明潜在的购房者是否被预先通过了房屋贷款。为了做出这个改变,D’Angelo想要在联系人对象上创建一个预审定的复选框。在Salesforce中,我们正在向标准对象添加自定义字段。让我们看看他是如何做到的。

  1. 从齿轮图标 (The gear icon to open Setup.), 单击Setup 启动设置页面。我们使用安装程序很多,所以请记住这一步!
  2. 单击 Object Manager 选项卡.
  3. 点击 Contact.
  4. 在字段和关系下,单击 New.
  5. 数据类型表示您的字段拥有哪种类型的信息。对于此字段,选择复选框,然后单击 Next.
  6. 字段标签是您在联系页面上看到的内容。输入资格预审?并点击 Next.
  7. 点击 Next 然后Save.

你只是定制你的第一个对象。做得好!

让我们来看看我们做了什么。打开 App Launcher The AppLauncher icon.并点击联系人。使用箭头列表视图箭头图标。查看所有联系人并单击联系人姓名。在“详细信息”选项卡下,您可以看到新的字段。现在米歇尔和其他经纪人更容易记录和检索这一重要的客户信息。

A contact detail page with the new Prequalified field displaying.

具有新的资格预审字段的联系人详细信息页面显示。
我们很快加入了这个字段。但事实证明,我们做的不仅仅是添加一个字段。同时,该平台也做了很多工作。显然,新的字段被添加到用户界面。您还可以运行报告并创建引用新字段的仪表板。该字段甚至已经准备好进入Salesforce移动应用程序。除了点击下一步之外,您无需执行任何操作。

这是Salesforce平台的强大功能。在下一个单元中,我们将讨论一些可以利用平台进行业务的方法。

Apex 测试(3)

学习目标

完成本单元后,您将能够:

  • 创建一个测试工具类。
  • 使用测试实用程序方法为各种测试用例设置测试数据。
  • 执行一个类中的所有测试方法。

为Apex测试创建测试数据

使用测试实用程序类为测试数据设置添加可重用的方法。

先决条件

如果您还没有这样做,请完成上一个单元“测试Apex触发器”中的先决条件。

添加一个测试工具类

让我们通过用一个实用程序类方法的调用替换测试数据创建来重构以前的测试方法。首先,您需要创建测试实用程序类。

TestDataFactory类是一种特殊的类,它是一个公共类,它是用isTest注释的,只能从正在运行的测试中访问。测试工具类包含可以被测试方法调用来执行有用任务的方法,例如设置测试数据。测试工具类从组织的代码大小限制中排除。

要添加TestDataFactory类:

  1. 在开发者控制台中,点击 File | New | Apex Class, 然后输入TestDataFactory作为类名,然后单击OK。
  2. 用下面的代码替换默认的类体。
    @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++) {
                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];
                // 对于刚插入的每个帐户,添加机会
                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));
                }
            }
            // 插入所有帐户的所有机会
            insert opps;
            
            return accts;
        }
    }
    此测试实用程序类包含一个静态方法createAccountsWithOpps(),该方法接受numAccts参数中保存的帐户数量以及为每个帐户(保存在numOppsPerAcct参数中)创建的相关机会数量。方法中的第一个循环创建了指定数量的帐户并将其存储在accts列表变量中。在第一个循环之后,将调用insert()DML语句在数据库的列表中创建所有帐户。

第二个循环创造了机会。由于每个机会组都链接到一个客户,所以外部循环通过客户进行迭代,并包含一个嵌套的循环,为当前客户创建相关的机会。下次运行嵌套循环时,使用add()方法将机会添加到同一个列表中。使用AccountId字段将机会链接到其父帐户。创建的所有机会总数是机会数量与客户数量的乘积(numOppsPerAcct * numAccts)。接下来,在循环之外有效地调用insert()DML语句,以便仅在一个调用中为所有帐户创建集合中的所有机会。

最后,这个方法返回新帐户的列表。

注意

尽管此方法不会返回相关的机会,但您可以通过编写SOQL查询来获取这些记录,该查询利用Account和Opportunity之间的现有关系,例如Testing Apex Triggers中的触发器中使用的查询。

调用测试数据创建的实用程序方法

现在您已经添加了测试实用程序类,请修改测试类以利用此类。在TestAccountDeletion类中,替换以// Test data setup开始的块,并以insert opp结束:

        // 测试数据设置
        // 通过调用实用程序方法创建一个拥有一个机会的帐户
        Account[] accts = TestDataFactory.createAccountsWithOpps(1,1);
TestDataFactory.createAccountsWithOpps(1,1)调用返回的数组包含一个Account sObject。

这是修改后的测试方法。更短的版本!

@isTest
private class TestAccountDeletion {

    @isTest static void TestDeleteAccountWithOneOpportunity() {
        // 测试数据设置
        // 通过调用实用程序方法创建一个拥有一个机会的帐户
        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('不能删除有相关机会的帐户.',
                             result.getErrors()[0].getMessage());
    }        
}

测试不同的条件

一种测试方法不足以测试触发器的所有可能输入。我们需要测试一些其他条件,例如何时删除没有机会的客户。我们还需要使用批量数量的记录来测试相同的方案,而不是只记录一个记录。这里是包含三个附加测试方法的测试类的更新版本。保存此类更新的版本。

@isTest
private class TestAccountDeletion {

    @isTest static void TestDeleteAccountWithOneOpportunity() {
        // 测试数据设置
        // 通过调用实用程序方法创建一个拥有一个机会的帐户
        Account[] accts = TestDataFactory.createAccountsWithOpps(1,1);
        
        // Perform test
        Test.startTest();
        Database.DeleteResult result = Database.delete(accts[0], false);
        Test.stopTest();

        // 验证删除是否应该被触发器停止,
        // 检查我们是否收到错误
        System.assert(!result.isSuccess());
        System.assert(result.getErrors().size() > 0);
        System.assertEquals('不能删除有相关机会的帐户',
                             result.getErrors()[0].getMessage());
    }
    
    @isTest static void TestDeleteAccountWithNoOpportunities() {
        // 测试数据设置
        // 通过调用实用程序方法创建一个没有机会的帐户
        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() {
        // 测试数据设置
        // 通过调用一个实用程序方法创建每个客户
        Account[] accts = TestDataFactory.createAccountsWithOpps(200,1);
        
        // 执行测试
        Test.startTest();
        Database.DeleteResult[] results = Database.delete(accts, false);
        Test.stopTest();

        // 验证每个记录。
        // 在这种情况下,删除应该已经被触发器停止,
        // 检查我们是否收到错误
        for(Database.DeleteResult dr : results) {
            System.assert(!dr.isSuccess());
            System.assert(dr.getErrors().size() > 0);
            System.assertEquals('不能删除有相关机会的帐户',
                                 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());
        }
    }
}
运行所有测试方法

最后一步是在我们的测试类中运行测试方法,现在该类包含更全面的测试,并被重构为使用测试数据工厂。由于您已经在TestAccountDeletion类中运行了测试,因此您可以重新运行此测试类以运行其所有测试方法。

  1. 要执行相同的测试运行,请单击测试选项卡,选择您的测试运行,然后单击Test | Rerun.
  2. 通过展开最新的测试运行来检查“测试”选项卡中的结果。测试运行应报告所有四个测试通过!

Apex 测试(2)

学习目标

完成本单元后,您将能够:

  • 编写对单个记录操作触发的触发器的测试。
  • 执行一个类中的所有测试方法。

测试Apex 触发器

在部署触发器之前,编写单元测试以执行触发触发器的操作并验证预期的结果。
让我们测试一下我们之前在Writing Apex Triggers单元中使用的触发器。如果一个客户记录有相关的机会,AccountDeletion触发器将阻止记录的删除。

先决条件

  1. 如果您尚未添加AccountDeletion触发器,请按照下列步骤操作。
    1. 在开发者控制台中,点击File | New | Apex Trigger.
    2. 输入AccountDeletion作为触发器名称,然后选择sObject的Account。点击Submit.
    3. 用下面的代码替换默认的代码。
      trigger AccountDeletion on Account (before delete) {
         
          // 如果他们有相关的联系人,防止删除帐户。
          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(
                  '不能删除有相关机会的帐号');
          }
          
      }
  2. 如果您在之前的单元中添加了AccountDeletion触发器,但已将其禁用,以便系统可以检查您的挑战,请重新启用它。
    1. 从设置中搜索 Apex Triggers.
    2. 在Apex触发器页面上,单击AccountDeletion触发器旁边的Edit
    3. 选择Is Active.
    4. 点击Save.
  3. 如果您的组织包含以前的单元(称为AddRelatedRecord,CalloutTrigger或HelloWorldTrigger)的触发器,请禁用它们。例如,要禁用AddRelatedRecord触发器:
    1. 从设置中搜索 Apex Triggers.
    2. 在Apex触发器页面上,单击AddRelatedRecord触发器旁边的 Edit .
    3. 取消选择Is Active.
    4. 点击Save.
  4. 要禁用HelloWorldTrigger和CalloutTrigger触发器,请重复上述步骤。

添加和运行单元测试

首先,我们开始添加一个测试方法。这个测试方法验证触发器设计要做什么(正面情况):防止一个帐户被删除,如果它有相关的机会。

  1. 在开发者控制台中,点击 File | New | Apex Class.
  2. 输入TestAccountDeletion作为类名称,然后单击 OK.
  3. 用下面的代码替换默认的类体。
    @isTest
    private class TestAccountDeletion {
    
        @isTest static void TestDeleteAccountWithOneOpportunity() {
            // 测试数据设置
            // 创建一个有机会的帐户,然后尝试删除它
            Account acct = new Account(Name='Test Account');
            insert acct;
            Opportunity opp = new Opportunity(Name=acct.Name + ' Opportunity',
                                           StageName='Prospecting',
    CloseDate=System.today().addMonths(1),
                                           AccountId=acct.Id);
            insert opp;
            
            // 执行测试
            Test.startTest();
            Database.DeleteResult result = Database.delete(acct, false);
            Test.stopTest();
    
            // 验证
            // 在这种情况下,删除应该已经被触发器停止,
            // 确认我们收到了错误
            System.assert(!result.isSuccess());
            System.assert(result.getErrors().size() > 0);
            System.assertEquals('不能删除有相关机会的帐户',
                                 result.getErrors()[0].getMessage());
        }
        
    }

    测试方法首先建立一个机会的测试帐户。接下来,它将删除测试帐户,该帐户触发AccountDeletion触发器。测试方法通过检查Database.delete()调用的返回值来验证触发器是否阻止删除测试帐户。返回值是一个Database.DeleteResult对象,其中包含有关删除操作的信息。测试方法验证删除不成功并验证获得的错误消息。

  4. 要运行此测试,请单击 Test | New Run.
  5. 在Test Classes下,单击TestAccountDeletion。
  6. 要将TemperatureConverterTest类中的所有方法添加到测试运行中,请单击添加 Add Selected.
  7. 点击Run.

    在最新运行的“测试”选项卡中找到测试结果。

TestAccountDeletion测试类只包含一个测试方法,用于测试单个帐户记录。此外,这个测试是针对正面的情况。始终测试更多方案,以确保触发器在所有情况下都能正常工作,包括删除没有机会的帐户和批量帐户删除。

测试数据是在测试方法内部设置的,添加更多的测试方法会耗费时间。如果您有许多测试方法,请将测试数据创建放在测试实用程序类中,并从多个测试方法中调用该实用程序类。下一个单元将向您展示如何利用测试工具类并添加更多的测试方法。

告诉我更多

测试方法包含Test.startTest()和Test.stopTest()方法对,该方法对代码块进行分隔,得到一组新的控制器限制。 在此测试中,测试数据设置在执行测试之前使用两个DML语句。 要测试Apex代码在限速范围内运行,请将数据设置的限制使用与测试隔离。 要隔离数据设置过程的限制使用,请将测试调用包含在Test.startTest()和Test.stopTest()块中。 测试异步Apex时也使用此测试块。 有关更多信息,请参阅使用限制,startTest和stopTest。

注意

开发人员控制台的一个已知问题是,在运行测试子集时,无法正确更新代码覆盖率。 要更新代码覆盖率结果,请使用 Test | Run All 而不是Test | New Run.

Apex 测试(1)

学习目标

完成本单元后,您将能够:

  • 描述Apex单元测试的主要优点。
  • 用测试方法定义一个类。
  • 执行班级中的所有测试方法并检查故障。
  • 创建并执行一组测试类。

Apex 单元测试

Apex测试框架使您能够为Force.com平台上的Apex类和触发器编写和执行测试。 Apex单元测试可确保您的Apex代码的高质量,并让您满足部署Apex的要求。

测试是成功实现长期发展的关键,也是开发过程的关键组成部分。 Apex测试框架可以轻松测试您的Apex代码。 Apex代码只能在沙箱环境或开发者组织中编写,而不能在生产环境中编写。 Apex代码可以从沙箱部署到生产组织。此外,应用程序开发人员可以通过将软件包上传到Force.com AppExchange,将Apex代码从开发人员组织分发给客户。除了对质量保证至关重要之外,Apex单元测试也是部署和分销Apex的要求。以下是Apex单元测试的好处。

  • 确保您的Apex类和触发器按预期工作
  • 拥有一套可以在每次更新类和触发器时重新运行的回归测试,以确保您对应用程序进行的未来更新不会破坏现有的功能
  • 满足部署Apex生产或通过包装向客户分销Apex的代码覆盖要求
  • 高质量的应用程序交付给生产组织,使生产用户的工作效率更高
  • 高品质的应用程序交付给包用户,这增加了客户的信任

注意

在每次重大服务升级之前,Salesforce都会通过名为Apex Hammer的流程代表您运行所有Apex测试。 Hammer进程在当前版本和下一版本中运行,并比较测试结果。此过程可确保您的自定义代码中的行为未因服务升级而改变。锤子过程选择性地选择组织,并且不运行在所有组织。发现的问题是基于特定的标准进行分类的。 Salesforce致力于解决每个新版本之前发现的所有问题。

维护数据的安全性是我们的首要任务。我们不会查看或修改您的组织中的任何数据,并且所有测试都是在安全的数据中心中运行的副本中完成的。

代码覆盖要求的部署

在部署代码或将其打包为Force.com AppExchange之前,至少有75%的Apex代码必须由测试覆盖,所有这些测试都必须通过。另外,每个触发器都必须有一定的覆盖范围。尽管代码覆盖率是部署的要求,但是不要只写测试来满足这个要求。确保在您的应用中测试常见用例,包括正面和负面的测试用例,以及批量和单一记录处理。

测试方法语法

测试方法不带任何参数,并具有以下语法:

@isTest static void testName() {
    // code_block
}
或者,一个测试方法可以有这样的语法:
static testMethod void testName() {
    // code_block
}
使用isTest注释而不是testMethod关键字更灵活,因为您可以在注释中指定参数。我们稍后会介绍一个这样的参数。

测试方法的可见性并不重要,因此将测试方法声明为公共或私有并不会造成影响,因为测试框架总是能够访问测试方法。为此,语法中省略了访问修饰符。

测试方法必须在测试类中定义,这些类是用isTest注释的类。这个样本类用一种测试方法显示了一个测试类的定义。

@isTest
private class MyTestClass {
    @isTest static void myTest() {
        // code_block
    }
}
测试类可以是私有的或公共的。如果您仅使用测试类进行单元测试,则将其声明为私有。公共测试类通常用于测试数据工厂类,稍后会介绍。

单元测试示例:测试TemperatureConverter类

下面这个简单的例子是三个测试方法的测试类。正在测试的类方法以华氏温度作为输入。它将此温度转换为摄氏温度并返回转换后的结果。让我们添加自定义类和它的测试类。

  1. 在开发者控制台中,点击 File | New | Apex Class, 然后输入TemperatureConverter作为类名称,然后单击OK.
  2. 用下面的代码替换默认的类体。
    public class TemperatureConverter {
        // 拍摄华氏温度并返回摄氏温度。
        public static Decimal FahrenheitToCelsius(Decimal fh) {
            Decimal cs = (fh - 32) * 5/9;
            return cs.setScale(2);
        }
    }
  3. 按下Ctrl + S保存你的课程。
  4. 重复之前的步骤来创建TemperatureConverterTest类。添加以下这个类。
    @isTest
    private class TemperatureConverterTest {
    
        @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);
        }
          
    }
    TemperatureConverterTest测试类通过以华氏温度的不同输入调用该方法来验证该方法是否按预期工作。每种测试方法验证一种类型的输入:暖温度,冰点温度,沸点温度和负温度。验证是通过调用System.assertEquals()方法完成的,该方法有两个参数:第一个是期望值,第二个是实际值。这个方法有另一个版本,它接受第三个参数 – 一个描述比较的字符串,在testBoilingPoint()中使用。如果断言失败,则会记录此可选字符串。

让我们来运行这个类中的方法。

  1. 在开发者控制台中,点击 Test | New Run.
  2. 在Test Classes下,单击TemperatureConverterTest.
  3. 要将TemperatureConverterTest类中的所有测试方法添加到测试运行,请单击 Add Selected.
  4. 点击Run.
  5. 在“测试”选项卡中,您可以看到运行中的测试状态。展开测试运行,然后再次展开,直到看到运行的单个测试列表。他们都有绿色的选中标记。
    Inspect test results in the Developer Console

运行测试后,将自动为组织中的Apex类和触发器生成代码覆盖率。您可以在开发者控制台的“测试”标签中查看代码覆盖百分比。在这个例子中,你测试过的类,TemperatureConverter类,具有100%的覆盖率,如图所示。

View code coverage percentage in the Developer Console

注意

无论何时您修改Apex代码,请重新运行测试以刷新代码覆盖率结果。

开发人员控制台的一个已知问题是,在运行测试子集时,无法正确更新代码覆盖率。要更新代码覆盖率结果,请使用Test | Run All 而不是Test | New Run.

虽然一种测试方法会导致TemperatureConverter类的全面覆盖,但测试不同的输入以确保代码质量仍然很重要。显然,不可能验证每个数据点,但可以测试常见的数据点和不同的输入范围。例如,您可以验证传递正数和负数,边界值和无效参数值以验证负面行为。 TemperatureConverter类别的测试验证常用数据点,如沸腾温度和负温度。

TemperatureConverterTest测试等级不包括无效输入或边界条件。边界条件是关于最小值和最大值。在这种情况下,温度转换方法接受一个可以接受大于Double值的Decimal。对于无效的输入,没有无效的温度,但唯一的无效输入为空。转换方法如何处理这个值?在这种情况下,当Apex运行时将参数变量解引用以评估公式时,它会引发System.NullPointerException。您可以修改FahrenheitToCelsius()方法来检查无效输入,并在这种情况下返回null,然后添加一个测试来验证无​​效的输入行为。

到目前为止,所有的测试都通过了,因为类方法中使用的转换公式是正确的。但是那很无聊!让我们尝试模拟一个失败,看看断言失败时会发生什么。例如,让我们修改沸点温度测试,并传递沸点摄氏温度(0而不是100)的错误预期值。这导致相应的测试方法失败。

  1. 将testBoilingPoint()测试方法更改为以下。
        @isTest static void testBoilingPoint() {
            Decimal celsius = TemperatureConverter.FahrenheitToCelsius(212);        
            // 模拟失败
            System.assertEquals(0,celsius,'不期望沸点温度');
        }
  2. 要执行相同的测试运行,请单击测试选项卡中的最新运行,然后单击 Test | Rerun.

    testBoilingPoint()中的断言失败,并引发一个致命错误(一个无法捕获的AssertException)。

  3. 通过展开最新的测试运行来检查“测试”选项卡中的结果。测试运行报告四分之一的测试失败。要获得有关失败的更多详细信息,请双击测试运行。

    详细的结果显示在单独的选项卡中,如图所示。

    Inspect results of a failed test in the Developer Console
  4. 要获取测试失败的错误消息,请双击失败测试的Errors列。你会看到以下内容。 Assertion Failed旁边的描述性文本是我们在System.assertEquals()语句中提供的文本。

    System.AssertException: Assertion Failed: 不期望沸点温度.: Expected: 0, Actual: 100.00

这些测试方法中的测试数据是数字而不是Salesforce记录。您将了解更多有关如何测试Salesforce记录以及如何在下一单元中设置数据的信息。

增加您的代码覆盖率

在编写测试时,尽可能实现最高的代码覆盖率。不要只瞄准75%的覆盖率,这是Force.com平台对部署和软件包的最低覆盖率。测试覆盖的测试用例越多,代码的健壮性就越高。有时,即使在为所有类方法编写测试方法之后,代码覆盖率也不是100%。一个常见原因是没有涵盖条件代码执行的所有数据值。例如,当你的类方法有if语句时,一些数据值往往会被忽略,这些语句会根据是否满足条件评估条件而导致不同的分支被执行。确保您的测试方法考虑到这些不同的值。

此示例包含类方法getTaskPriority(),它包含两个if语句。这种方法的主要任务是根据给定的导联状态返回一个优先级字符串值。该方法首先验证状态,如果状态无效则返回null。如果状态是CA,则方法返回“高”;否则,返回任何其他状态值的“正常”。

public class TaskUtil {
    public static String getTaskPriority(String leadState) {
        // 验证输入
        if (String.isBlank(leadState) || leadState.length() > 2) {
            return null;
        }
            
        String taskPriority;
        
        if (leadState == 'CA') {
             taskPriority = 'High'; 
        } else {
             taskPriority = 'Normal';
        }
        
        return taskPriority;
    }
}
注意

等号运算符(==)执行不区分大小写的字符串比较,因此不需要先将字符串转换为小写字母。这意味着传入’ca’或’Ca’将满足字符串字面值’CA’的相等条件。

这是getTaskPriority()方法的测试类。测试方法只需调用一个状态(’NY’)的getTaskPriority()。

@isTest
private class TaskUtilTest {
    @isTest static void testTaskPriority() {
        String pri = TaskUtil.getTaskPriority('NY');
        System.assertEquals('Normal', pri);
    }
}
让我们在开发者控制台中运行这个测试类(TaskUtilTest),并检查测试覆盖的相应TaskUtil类的代码覆盖率。测试运行结束后,TaskUtil的代码覆盖率显示为75%。如果您在开发人员控制台中打开此课程,则会看到六个蓝色(被覆盖)线条和两个红色(未被覆盖)线条,如图所示。
Lines covered for the TaskUtil class in the Developer Console

第五行没有被覆盖的原因是因为我们的测试类没有包含一个测试来传递一个无效的状态参数。同样,第11行没有被覆盖,因为测试方法没有通过“CA”作为状态。我们再添加两个测试方法来覆盖这些情况。以下显示了添加testTaskHighPriority()和testTaskPriorityInvalid()测试方法后的完整测试类。如果您重新运行此测试类,TaskUtil的代码覆盖率现在为100%!

@isTest
private class TaskUtilTest {
    @isTest static void testTaskPriority() {
        String pri = TaskUtil.getTaskPriority('NY');
        System.assertEquals('Normal', pri);
    }
    
    @isTest static void testTaskHighPriority() {
        String pri = TaskUtil.getTaskPriority('CA');
        System.assertEquals('High', pri);
    }
    
    @isTest static void testTaskPriorityInvalid() {
        String pri = TaskUtil.getTaskPriority('Montana');
        System.assertEquals(null, pri);
    }
}
创建并执行测试套件

测试套件是一起运行的Apex测试类的集合。例如,创建一套您每次准备部署时运行的测试,或者Salesforce发布新版本。在开发者控制台中设置一个测试套件来定义一组定期一起执行的测试类。

您现在在您的组织中有两个测试课程。这两个阶级是不相关的,但让我们暂时假装他们是。假设有些情况下你想运行这两个测试类,但不想运行你的组织中的所有测试。创建一个包含两个类的测试套件,然后在套件中执行测试。

  1. 在开发者控制台中,选择 Test | New Suite.
  2. 输入TempConverterTaskUtilSuite作为套件名称,然后单击OK.
  3. 选择TaskUtilTest,按住Ctrl键,然后选择TemperatureConverterTest
  4. 要将所选测试类添加到套件,请单击 >.

    Test suite editing window with two selected test classes

  5. 点击Save.
  6. 选择Test | New Suite Run.
  7. 选择TempConverterTaskUtilSuite,然后单击>将TempConverterTaskUtilSuite移动到选择的测试套件列。
  8. 点击Run Suites.
  9. 在“测试”选项卡上,监视测试运行状态。展开测试运行,然后再次展开,直到看到运行的单个测试列表。就像在单个测试方法的运行中一样,您可以双击方法名称以查看详细的测试结果。

创建测试数据

在测试方法中创建的Salesforce记录不会提交到数据库。当测试结束执行时,它们会回滚。这个回滚行为对于测试是很方便的,因为在测试执行后你不必清理你的测试数据。

默认情况下,除了访问设置和元数据对象(如User或Profile对象)外,Apex测试不能访问组织中预先存在的数据。为您的测试设置测试数据。创建测试数据可使您的测试更健壮,并防止组织中缺少或更改数据导致的故障。您可以直接在测试方法中创建测试数据,也可以使用实用程序测试课程,稍后您将会看到。

注意

尽管这样做不是最佳实践,但有时候测试方法需要访问预先存在的数据。要访问组织数据,请使用@isTest注释测试方法(SeeAllData = true)。本机中的测试方法示例不访问组织数据,因此不使用SeeAllData参数。

告诉我更多…

  • 您可以在每个组织中最多保存3 MB的Apex代码。用@isTest注释的测试类不计入此限制。
  • 即使测试数据回滚,也不会使用单独的数据库进行测试。因此,对于某些具有唯一约束的字段的sObjects,插入重复的sObject记录会导致错误。
  • 测试方法不发送电子邮件。
  • 测试方法不能调出外部服务。您可以在测试中使用模拟标注。
  • 在测试中执行的SOSL搜索返回空结果。为了确保可预测的结果,使用Test.setFixedSearchResults()来定义搜索返回的记录。