Hi friends, As far as I know test isolation is widely used in SAP internal to build unit test code, at least in my team. Test isolation in unit test means that in your production code you make use of some API(class method/Function module) which are developed by other team, and you would not like to really consume them during your unit test, since you would not accept that most red lights in your unit test report are caused by the bugs in those external API,right? Instead, you expect that the call of those external API during your unit test execution will be replaced by some dummy code written by yourself. I will show you four different ways to achieve that. The example comes from one productive class in my project. For simplicity reasons I don’t list unrelevant code here. The class is ZCL_DESTRUCTION_IMG_TOOL_S1.
The main logic is doing a cleanup work: loop every work list item, check whether it has some dependent object. If so, delete it.
method RUN.
DATA: lv_social_post_id TYPE string.
fill_worklist( ).
LOOP AT mt_worklist INTO lv_social_post_id.
IF dependent_object_existed( lv_social_post_id ) = abap_false.
delete( lv_social_post_id ).
ENDIF.
ENDLOOP.
endmethod.
The worklist is just hard-coded:
method FILL_WORKLIST.
CLEAR: mt_worklist.
APPEND '20130001' TO mt_worklist.
APPEND '20130002' TO mt_worklist.
APPEND '20130003' TO mt_worklist.
endmethod.
The reason why test isolation is used in our unit test is because in method dependent_object_existed, we call an API provided by another team, and we don’t want that API to be really executed during our unit test execution. For demonstration reason, I use the following code to simulate the production code. It means during the unit test on this class, the following code is NOT expected to be executed at all.
method DEPENDENT_OBJECT_EXISTED.
WRITE: / 'Productive code to check dependent object existence for ID: ' , iv_social_post_id.
endmethod.
Approach1: test subclass instead
(1) Change the visibility of method DEPENDENT_OBJECT_EXISTED from private to protected. The idea is in this approach, we create a sub class ( a local test class) which inherits from ZCL_DESTRUCTION_IMG_TOOL_S1. Since the DEPENDENT_OBJECT_EXISTED is now protected, we have the chance to redefine it in the local test class.
The mock code is simple like below:
METHOD dependent_object_existed.
WRITE: / 'Test mock code to check dependent object existence for ID: ' , iv_social_post_id.
ENDMETHOD.
And the code for method start:
method start.
f_cut = lcl_Destruction_Test=>get_sub_instance( ).
f_cut->run( ).
endmethod.
In this approach, actually the class being unit test are not lcl_destruction_test, instead of the original class ZCL_DESTRUCTION_IMG_TOOL_S1.
when execution comes into run method, since the subclass only redefines the very method dependent_object_existed, so the execution of the left methods are still using the code of ZCL_DESTRUCTION_IMG_TOOL_S1. That means all methods of ZCL_DESTRUCTION_IMG_TOOL_S1 except dependent_object_existed will be covered by unit test.
And when execution comes into method dependent_object_existed,since currently “me” points to the local test sub class, so the mock code will be executed, which is just what we expected.
The limitation of this approach is, if the author of class ZCL_DESTRUCTION_IMG_TOOL_S1 insists on that it should be defined as final, it is impossible to define any sub class of it.
Approach2 – interface extraction + optional argument
The idea is to extract the logic written in method dependent_object_existed and put its implementation into method dependent_object_existed of a new interface ZIF_SOC_DEPENDENCY_DETECTOR instead. Via such abstraction, the loose coupling of dependency detection call and its implementation is achieved.
Necessary change on production class ZCL_DESTRUCTION_IMG_TOOL_S2 source code:
(1) Private method dependent_object_existed can be removed now.
(2) Create a local class to implement the productive logic of dependency detection as usual:
(3) Create an optional argument of method run.
(4) In method run, if no reference is passed in for io_dep_obj_detector, the default one for production use will be called (line5).If there is indeed one dependent object detector passed in, use that one. (line7)
Also the previous method dependent_object_existed is removed; the interface method call is used instead.
(5) The unit test class also implements interface method http://dependent_object_existed.In unit test code, the optional parameter of method run will be filled, so that the redefined dependency detection logic implemented in interface method in unit test code will be called instead ( according to the logic in step4, line 7)
Now the possibility is given for consumers to provide their own dependency determination logic by implementing interface and filling the optional parameter of method run; however this is not what we expected in the beginning. Signature of method run is changed, which is a non-critical change. (Adding a new optional method parameter is not an incompatible change) In my opinion it could not be regarded as a 100% test isolation solution.
Approach3 – Dynamic detector initialization
Interface extraction is also necessary for this solution. Necessary change on production class ZCL_DESTRUCTION_IMG_TOOL_S3’s source code:
(1) Create a local class to implement the productive logic of dependency detection just the same as approach2. (2) Add a new static member attribute for technical name of dependency class name. Default value is local class name created in step1:
(3) Initialize the detector instance according to its name maintained in member attribute mv_detector_type_name. Since its default value is the local class LCL_PROD_DEP_DETECTOR, so in the runtime the productive detection logic will be called.
(4) Define the unit test class as the friend of class ZCL_DESTRUCTION_IMG_TOOL_S3, so that it can alter even the private attribute mv_detector_type_name of ZCL_DESTRUCTION_IMG_TOOL_S3.
In the unit test code, just add one line( line 62 ). Now the detection logic redefined in unit test class will be called.
Approach3 is superior compared with approach2 in that no method signature change is required. Class consumer will have no chance to pass their own detection logic into class in a normal way. However, a new class member attribute is introduced, which could be not necessary in the next approach 4.
Approach4 – detector reference replacement
Similar with approach 3 to some degree. Necessary change on production class ZCL_DESTRUCTION_IMG_TOOL_S4 source code:
(1) Implement the productive dependency detection logic in local class lcl_prod_dep_detector just the same as approach3. (2) Initialize the productive detector instance in CONSTRUCTOR.
method CONSTRUCTOR.
CREATE OBJECT mo_dep_obj_detector TYPE lcl_prod_dep_detector .
endmethod.
(3) Implement the interface method in test class. (4) Define unit test class as friend of ZCL_DESTRUCTION_IMG_TOOL_S4. (5) In unit test code, replace the instance of dependency detector with unit test class reference itself, so that our own logic would be called in unit test:
No new attribute or method interface change is required in this solution. This solution should be used for test isolation whenever possible.
要获取更多Jerry的原创文章,请关注公众号"汪子熙":
相关推荐
本书名为《SAP ABAP Hands-On Test Projects with Business Scenarios》,是一本专注于SAP ABAP(高级业务应用编程)的英文版电子书,旨在通过实际的商业场景案例,帮助读者练习并掌握SAP ABAP的编程知识。...
abap sap 测试题,abap sap 测试题 ,abap sap 测试题
11. **Web Dynpro**:ABAP Web Dynpro是一种用于构建企业级Web应用程序的技术,它提供了可视化设计工具和强大的组件模型。 12. **ABAP工作流**:用于自动化业务流程,如审批流程。开发者可以定义工作流模板,根据...
15. **ABAP Test Classes and Unit Testing**:理解单元测试的重要性,以及如何编写和执行ABAP单元测试。 16. **ABAP Development Tools (ADT)**:介绍现代的ABAP开发环境,如使用Eclipse集成开发环境进行ABAP编程...
ABAP OLE开发技术是一门针对SAP系统中ABAP编程语言进行自动化操作的技术。通过学习ABAP OLE技术,开发者能够控制其他程序,使得SAP系统能够自动化执行其他程序的任务,例如Microsoft Office应用程序的操作,这种技术...
abap English and test
ERP系统信息化资料:abap+测试题--不带答案.doc
ABAP常用开发技术讲义 ABAP常用开发技术讲义是SAP系统中的一个重要组件,用于开发各种报表程序。报表程序是从数据库中抓取数据,并将其整理出来,以供企业高层或相关人员查看。以下是ABAP常用开发技术讲义中的知识...
SAP提供了强大的调试工具,如ABAP Debugger,用于查找和修复代码错误,同时支持单元测试和集成测试。 10. 应用开发实例: 手册中可能包含报表开发、GUI屏幕设计、BADI(Business Add-In)应用、RFC(Remote ...
由于提供的内容较为模糊,我们将基于文档中提到的关键点来展开讨论,包括新的 ABAP 编辑器、动态编程与 RTTS(Run-Time Type System)、代码检查器以及 ABAP 单元测试等主题。 #### 新的 ABAP 编辑器 (The New ABAP...
ABAP提供了内置的测试框架,如Test Classes和Unit Tests,用于编写单元测试。这些测试类可以验证单独的函数模块、方法或类的行为,确保它们按照预期工作。在棉绒(可能是指细致入微的测试)的概念下,我们需要对...
9. **ABAP Test Framework**: ABAP提供了一套完整的测试框架,如ABAP Unit,用于编写单元测试,确保代码质量并减少错误。 10. **Web Dynpro ABAP**: 是ABAP WorkBench的一部分,用于创建复杂的Web应用程序。它提供...
9. **ABAP单元测试**:插件提供了编写和执行ABAP单元测试的功能,遵循TDD(测试驱动开发)原则,确保代码的正确性和稳定性。 10. **文档与帮助**:Eclipse ABAP插件通常会集成SAP官方的ABAP帮助文档,方便开发者...
总的来说,"abap xlsx2 demo 程序"是一个实用的学习资源,展示了在ABAP环境中处理.xlsx文件的技术和最佳实践。它涵盖了文件上传、数据转换、类型映射等多个方面,对于那些需要在SAP系统中与Excel交互的开发者来说,...
江正军技术博客中的ABAP技术总结给出了一个全面的ABAP技术概览,涵盖了从基础语法到高级技术的各个方面,为SAP开发者提供了一种系统学习和快速参考的途径。随着SAP系统及其技术的发展,ABAP作为其核心编程语言,将...
ABAP 屏幕编程是 SAP 系统中的一种编程技术,用于创建交互式屏幕,以便用户可以与 SAP 系统进行交互。ABAP 屏幕编程教程旨在为开发者提供详细的指南,帮助他们快速掌握 ABAP 屏幕编程的技术。 第一部分:ABAP 屏幕...
本文将详细解析如何使用SE30工具来测试和分析ABAP程序的运行效率,以及如何定位并优化最耗时的代码段。 SE30是SAP提供的一个内置工具,专门用于性能测试和分析。它可以帮助开发者识别程序中的瓶颈,从而有针对性地...
在SAP系统中,ABAP调用ABAP Proxy是一种常见的技术操作,用于在不同系统间或者同一系统内的组件之间实现通信。ABAP Proxy是SAP提供的一个强大的接口技术,它允许开发者创建安全、高效的远程调用机制。接下来,我们将...
《SAP ABAP开发技术详解(实例篇)(第二版) [1] 》除了对对SAP ABAP开发所需的常用技术(SAP报表、批量导入、对话程序、函数)做了详尽的介绍,包括基本报表、交互式报表、复杂报表、ALV(SAP List Viewer)报表、...