
Great software is testable.
No matter how pretty your code looks, if you cannot properly test your program, it will be quite hard to maintain/enhance. This is a big problem for the users, just that they might not know or care, but also for you, because software and applications are constantly changing, evolving, in some cases mutating into some other thing very different from the original scope- let's get real here. And guess who will have to do the dirty work?
So often we find ourselves in one of these situations: Either we are asked to change our own code - more desirable, but likely that we won't remember anything of what we wrote at the time. Or we need to change someone else's code - less desirable, highly probable. How can we be sure that we won't break anything after implenting changes if the code cannot be tested? The traditional approach that I've seen over the course of 10 years is this:
"Of course, they were testing with X data set and we ran our tests with Y data set" will be the first excuse. And even if it's true, the real issue is that the software is weak, not robust, it can't be tested without real data. In other words, the program has dependencies, thus it is impossible to test.
I've been reading a lot about Test-Driven development, and nowadays I'm starting to feel like Neo in The Matrix: I know kung-fu. Seriously, in my experience, TDD is the way to go when it comes to delivering good, quality software.
How do you create good tests, then? Well this feels like kind of a journey, there are many things to learn. Once again, I couldn't recommend more bfeeb8ed7fa64a7d95efc21f74a8c135book ABAP to the future, it has been my guide and also inspired me to start writing these posts.
First of all, ABAP Unit does not have to be a pure technical tool, only available to developers. You don't need a developer key to run unit tests over an ABAP program, therefore anyone with the proper authorizations to display programs/classes should be able to run the tests. So what if we also involve our business experts and functional consultants?
Well, with Behaviour-Driven development we can accomplish this. bfeeb8ed7fa64a7d95efc21f74a8c135talked about it already back in 2013, I'm just discovering this now. BDD is all about simplification inside your test methods, so the methods labeled FOR TESTING in abap unit will have descriptions that make sense to developer, business analyst and user. You can accomplish this by setting each test method that complements the phrase "It should....". Then inside of this method, you create 3 helper methods following the pattern "Given .... (initial condition)", "When .... (method to test)", "Then .... (check result)".
This is how I refactored my test class for the ZCL_INVENTORY class:
class lcl_test_class definition deferred.
"Allow access to private components within the class
class zcl_inventory 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_inventory,
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_inventory=>guitars_tab.
methods:
setup,
"User Acceptance tests:
"IT SHOULD....................
add_guitar_to_inventory for testing,
add_duplicate_and_get_error for testing,
search_within_the_inventory for testing,
"GIVEN ..................................................
given_guitar_attribs_entered,
given_initial_inventory,
"WHEN ..................................................
when_guitar_is_added,
when_same_guitar_twice,
when_guitar_is_searched,
"THEN ..................................................
then_inventory_has_guitar,
then_exception_is_raised,
then_guitar_is_found,
"Other helper methods
load_mockups returning value(re_guitars) type ty_guitars.
endclass.
So the idea is to include "IT SHOULD" methods as they came right out of the functional specification document. In my example, The ZCL_INVENTORY class should be able to:
method add_guitar_to_inventory.
given_guitar_attribs_entered( ).
when_guitar_is_added( ).
then_inventory_has_guitar( ).
endmethod.
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 = 'Stratocaster'.
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 = 'FE34000'
price = '1745.43'
specs = guitar_spec ).
guitar_to_add = new zcl_guitar( guitar_record ).
endmethod.
method when_guitar_is_added.
try.
mo_class_under_test->add_guitar( guitar_to_add ).
catch zcx_guitar.
"Oops
endtry.
endmethod.
method then_inventory_has_guitar.
data(guitar) = mo_class_under_test->guitars[ serial_number = 'FE34000' ].
cl_abap_unit_assert=>assert_not_initial( act = guitar
msg = 'Guitar is not in inventory' ).
endmethod.
Isn't it nice? We ended up with a nicely written Unit Test which is meaningful to the current developer and those who will come after, to the functional consultants, business users, and even managers.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
3 | |
3 | |
2 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 |