编写可测试代码的ABAP编程方法

举报
雨绸缪 发表于 2023/07/31 17:03:32 2023/07/31
【摘要】 原文链接:ABAP Programming approach to writing testable code作者:Akash Jain  阿卡什·贾因 | August 2, 2019无论我们的代码有多好,如果我们不能正确地测试它,修改或增强它是一项乏味的任务。这种情况会给用户和开发人员带来问题。 简介由于需求在开发过程中经常变化,你需要不断地修改代码。有时,需求的变化可能涉及到流程的完全...

原文链接:ABAP Programming approach to writing testable code

作者:Akash Jain  阿卡什·贾因 | August 2, 2019

无论我们的代码有多好,如果我们不能正确地测试它,修改或增强它是一项乏味的任务。这种情况会给用户和开发人员带来问题。

简介

由于需求在开发过程中经常变化,你需要不断地修改代码。有时,需求的变化可能涉及到流程的完全改变。

编写可测试的代码总是比实际测试你的代码更困难。然而,从长远来看,可测试的代码使开发人员的生活比测试代码的人更容易。

你可能会面临以下情况:

  • 您需要更改自己的代码。您可能喜欢这个想法,但您不记得您最初编写的代码的细节。
  • 你必须修改别人的代码。这种情况并不理想,但却很常见。

如果你不能测试代码,你怎么能确定你在实现更改后不会破坏任何东西呢?多年来,我们看到的传统方法包括以下几种:

  • 在开发环境中写一些测试,并检查是否有转储的情况。
  • 转移到质量测试环境,再次测试。
  • 交给模块顾问,让他们在他们的终端进行测试。
  • 发布给用户进行用户验收测试(UAT)。

当有人遇到代码的问题时,我们很可能会归咎于测试数据的差异。即使这是真的,真正的问题是,软件写得不好,不够健壮。没有真实的数据,你无法测试它。换句话说,程序有依赖性,你无法测试它。

测试驱动开发和 ABAP

测试驱动开发(Test-driven development,TDD)解决了这些问题,使你能够交付高质量的软件和产品。

TDD 是一个软件开发过程,它依赖于一个非常短的开发周期的重复:当需求转化为非常具体的测试用例时,软件就会被改进,只通过新的测试。(维基百科)

image.png

在 ABAP 中,所有的代码都被转换为 ABAP 单元,它只不过是一段特定的代码。测试 ABAP 单元不一定是一个由开发人员执行的纯技术过程。因为你不需要开发人员的密钥来运行 ABAP 程序的单元测试,所以任何具有显示程序或类的适当授权的人都应该能够运行测试。作为一个最佳实践,只要有可能,请尽可能让我们的业务专家和职能顾问参与测试。

行为驱动开发

行为驱动开发(Behavior-driven development,BDD)是由 TDD 产生的一种软件开发过程。BDD 将 TDD 的一般技术和原则与领域驱动设计(domain-driven design)和面向对象的分析和设计的思想相结合,为软件开发和管理团队提供共享工具和共享流程,以协作进行软件开发。(维基百科)

BDD 简化了测试方法,所以在 ABAP 单元中标注的测试方法应该有对开发人员、业务分析人员和用户有意义的描述。你可以通过设置每个测试方法使其满足 IT SHOULD(应该是这样的) 这句话来实现。

然后在这个方法里面,你通过使用以下模式创建三个辅助方法:

  • GIVEN:包括程序收到的输入或初始条件。
  • WHEN: 描述你要测试的活动。
  • THEN:指定成功和失败的结果。

重构可测试类 Demo

下面的代码示例使用伪代码定义流程,是 zcl_instruments 类的重构测试类示例。

class lcl_test_class definition deferred.

"Allow access to private components within the class

class zcl_instruments definition local friends lcl_test_class.

class lcl_test_class definition final for testing
  duration short
  risk level harmless.

  private section.

    types: ty_guitars type standard table of zguitars with empty key.

    data: mo_class_under_test type ref to zcl_instruments,
	   guitar_instance type ref to zcl_guitar,
             guitars type ty_guitars.
	   guitar_to_add type ref to zcl_guitar.
	   guitar_to_search type ref to zcl_guitar.
	   mo_exception_raised type abap_bool.
	   found_guitars type zcl_instruments=>guitars_tab.


    methods:
      setup,
      "User Acceptance tests:

      "IT SHOULD....................
      add_guitar_to_instruments for testing,
      add_duplicate_and_get_error for testing,
      search_within_the_instruments for testing,

      "GIVEN ..................................................
      given_guitar_attribs_entered,
      given_initial_instruments,

      "WHEN ..................................................
      when_guitar_is_added,
      when_same_guitar_twice,
      when_guitar_is_searched,

      "THEN ..................................................
      then_instruments_has_guitar,
      then_exception_is_raised,
      then_guitar_is_found,

      "Other helper methods
      load_mockups returning value(re_guitars) type ty_guitars.

endclass.

您应该包括 IT SHOULD 直接从功能规范文档中出来的方法。

在此示例中,zcl_instruments 类应该能够:

  • 将吉他添加到乐器中
  • 限制重复行为
  • 在乐器中搜索任何特定的吉他

下面的示例显示了该方法的实现 add_guitar_to_instruments() :

method add_guitar_to_instruments.

    given_guitar_attribs_entered ().

    when_guitar_is_added ().

    then_instruments_has_guitar ().

  endmethod.

若要将吉他添加到乐器,请从一些吉他属性开始,将吉他添加到乐器,然后检查是否成功添加。如果在运行此方法的测试时没有绿色,则表明过程的这一部分出了问题。

下面的 given_guitar_attribs_entered() 方法只初始化一个吉他对象。

method given_guitar_attribs_entered.

  data: guitar_spec_attributes type zcl_guitar_spec=>ty_guitar_attributes.

    guitar_spec_attributes-builder = zcl_enum_builder=>fender.
    guitar_spec_attributes-model    = 'XYZ'.
    guitar_spec_attributes-type     = zcl_enum_guit_type=>electric.
    guitar_spec_attributes-backwood = zcl_enum_wood=>maple.
    guitar_spec_attributes-topwood = zcl_enum_wood=>maple.

    data(guitar_spec) = new zcl_guitar_spec (guitar_spec_attributes).

    data(guitar_record) = value zcl_guitar=>ty_guitar_attributes (serialnumber = 'ABC0001'
                                                                   price = '1000'
                                                                   specs = guitar_spec).
    guitar_to_add = new zcl_guitar (guitar_record).


  endmethod.

BDD WHEN 描述的一部分,来自被测试的类,使您能够测试该方法。

method when_guitar_is_added.

    try.
        mo_class_under_test->add_guitar (guitar_to_add).
      catch zcx_guitar.
        "Oops
    endtry.

  endmethod.

最后,您可以使用以下方法检查对象乐器是否有吉他。此检查表示BDD部分的helper方法 Then 。

method then_instruments_has_guitar.

    data(guitar) = mo_class_under_test->guitars [ serial_number = 'ABC0001'].

    cl_abap_unit_assert=>assert_not_initial (act = guitar
                                             msg = 'Guitar is not in instruments').

  endmethod.

总结

本博客强调了编写可测试代码的重要性,并展示了如何做到这一点。通过专注于测试驱动开发,您可以调整您的编程风格以包含可测试代码。因此,您最终会得到干净、易于维护和可重用的代码。编写可测试的代码可以帮助你成为一个更好的开发人员。有时,当交付期限更紧时,很容易忽略代码的可测试性方面,这样做可能会保存时间。然而,从长远来看,您最终会花费更多的时间和资源来修复 bug。

因此,通过采用这里描述的测试驱动开发概念,您不仅可以使自己的工作更轻松,而且还可以帮助下一个开发您的代码的开发人员。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。