PBUnit/PowerUnit Quick Start

  1. Download latest version. To eliminate confusion, I bumped up the version number to 9, to indicate this is to PowerBuilder version 9. You should be able to upgrade/migrate this to any Powerbuilder version higher than 9.
  2. Create your demo app, add pbunitfunc.pbl and pbunit.pbl into your app’s lib list.2_demo_app_lib_list.jpg
  3. Create a nvo, this is the object to be tested later.3_demo_nvo.jpg
  4. OK, let create our first PowerBuilder test case. You have 2 options to put all test cases, a) same target as the demo app; b) create a different target to hold all test cases. (This needs duplicate all app settings in your new application object, especially for pfc app) To make it easier to start, we use the same target, which means testing object and tested object are in same project.
    Test case object needs to inherit from testcase object in pbunit.pbl.4_inherit_test_case.jpg
  5. The code in test case looks like this:41_code_test_case.jpg
  6. Save this testcase object as n_cst_math_service_tests. To make auto-test run, I set a rule: all test case object should end up with ‘tests’, unless I can find a way to detect the ancestor of PowerBuilder’s object.
  7. Launch your pbunit.exe. Load this new target.Click ‘Run’ button. You should see your green bar now. Note, the  ‘Run All’ button is  for auto-run usage,  a xml test result file is generated afterwards. Then  can be  embedded into CouriseControl continues auto build server.  8_pbunit_test_result.jpg

32 thoughts on “PBUnit/PowerUnit Quick Start

  1. Hi Frank,

    I’ve got the latest version of PBUnit (20080714), so there are at least two of us using it. 😉

    However, i’m having the following problem: as I debug, the app hangs in pbunit in
    of_getcurrenttest() at line:
    inv_test = create using is_CurrentTestObject
    I’ve tried to let it run for 5 minutes or so, but it should never take that long to load a simple test case. Any ideas?


    Erik Swanson

    • Great, I feel a little bit warmer now.

      PBUnit can only run in exe mode. Debug mode never worked. Don’t know why, please try launch executable and make sure it’s the right PowerBuilder version.

      • It’s because there is a SetLibraryList() call along the way that will fail if you’re running from within PB. According to the documentation it always returns -1 and has no effect, if you’re running from the IDE.

    • If you want to run unit tests from PB, you have to have a PBUnit target with the full Library List of the application. PBUnit will sitll try to set the Library List to no effect, but the libraries will already be in the Library List. Below is what I have in the application object for testing objects in a PFC-based app.

      global type pbunit_hbapp from application
      end type
      global n_tr sqlca
      global dynamicdescriptionarea sqlda
      global dynamicstagingarea sqlsa
      global n_err error
      global n_msg message
      end forward
      global variables
      hb_n_cst_appmanager gnv_app
      // ======
      // from pbunit app
      long gl_returnCode
      boolean gb_commandline = false
      end variables
      global type pbunit_hbapp from application
      string appname = "pbunit_hbapp"
      end type
      global pbunit_hbapp pbunit_hbapp
      on pbunit_hbapp.create
      message=create n_msg
      sqlca=create n_tr
      sqlda=create dynamicdescriptionarea
      sqlsa=create dynamicstagingarea
      error=create n_err
      end on
      on pbunit_hbapp.destroy
      end on
      event open;n_pbunit_hbapp_connectservice lnv_connectserv
      lnv_connectserv = Create using "n_pbunit_hbapp_connectservice"
      If lnv_connectserv.of_ConnectDB ( ) = 0 Then
      	gnv_app = create using "hb_n_cst_appmanager"
      End if
      Destroy lnv_connectserv
      // ================================
      // from pbunit app
      n_pbunit_LibraryManager	lm
      lm = create n_pbunit_LibraryManager;
      lm.StartPBUnit (commandline);
      end event
      event close;n_pbunit_hbapp_connectservice lnv_connectserv
      lnv_connectserv = Create using "n_pbunit_hbapp_connectservice"
      lnv_connectserv.of_DisconnectDB ( )
      Destroy lnv_connectserv
      // ==========================
      // from pbunit app
      Message.LongParm = gl_returncode
      end event
      event systemerror;// ==========================
      // from pbunit app
      Message.LongParm = gl_returncode
      end event
  2. Frank, do you have any test example of lets say ue_save event? I see how you would use PBUnit for testing particular calculative functions, but what about the rest of the application? Thanks!

    • Testing event is possible, I don’t have an example yet, but the idea is to move all the logic code into a nvo which is easier to setup. Making application testable is more focusing on design than coding. That’s the core of TDD.

      • Yes, I definitly agree. But it looks like that in the applications which are 5-10 years old the use of PBUnit can be very limited. Unless someone is ready for a complete re-write :).
        Thank you.

  3. Hello,
    sorry for my English, I’m French.
    I work almost 12 PB 11.
    I am currently looking for an application like PBUnit. Apart from this, as there are others? During my search through google, I found none!
    This will allow me to compare them and choose the one that meets at most all my criteria.

    Thank you for your help.

  4. @Goupil: I don’t know of any unit testing software for PowerBuilder other than what’s been mentioned here, and PBUnit is the best of the ones I’ve found.

  5. Hi Frank,

    Your “how to” was very helpful Thanks so much!
    There is a tiny issue though with the screen shot on the nvo object. The of_add should be created as an event, not a functions.


  6. Has anybody hit problems with PBUnit / PowerUnit and globals?

    My project uses some global variables and the functionality I’d like to test with my test cases will be using some of those globals.

    When I run PBUnit attempt to run a test case it gives me an error like this:

    unresolvable external [global variable name] when linking reference

    Is there a solution to this without removing all globals from my code?


      • Thanks for the response, I intended to leave a comment thanking you earlier.

        So thanks! Refactoring new code is easy, but introducing a unit testing framework into a legacy project that makes use of globals would be tricky and take a lot of work.

        Thanks also to Hugh who provided a possible solution to using globals.


  7. See my post from August 26, 2010 (above). That setup allows you to test components that reference globals (in my case PFC’s gnv_app). I never run that target as exe, I just run it directly from the IDE.

      • The CI server can build the unit-test target and then run it with the same args you’d pass PBUnit (it’s just PBUnit with some more stuff loaded). You can have the unit test target use the main app’s PBDs. The CI server can build the unit test target after it builds the main app, which should be very fast since it’s mostly PBDs. I’d comment out the load library stuff if I was going to run the unit-test target as EXE. Can’t remember if I’ve got it commented in my setup but of course it does nothing when running in PB.

        My present needs are different. I want to write tests, write code, run tests, lather, rinse, repeat until the bar is green. I need to get a lot more people here writing tests before we can get to CI & test.

    • Hugh,

      We are developing a PFC based application and we want to implement Unit Testing. Your explanation was helpful. The problem we faces is that all our CRUD actions in the application are run on Shared DWs (sharedata) or linked DWs (linkage service). I would like to know if you have found a way to automate the test on CRUD actions on these kind of DWs. I appreciate your help.

      Thanks in advanced.


      • I test my shared DataWindows in PBUnit. The tests create DataStores for the source and target, set the source, then set each target and check that `shareData` succeeds. We have some shared DataWindows that use multiple sources and we test each source with each target.

        What are your concerns that you want to test? Do you want to be sure that database changes don’t break you DataWindows? Your test can extract the SQL from the DataWindow then create a temporary dw with `syntaxFromSQL`. If the create succeeds the SQL is valid. Then check the datatype and size if applicable of each column in the dw under test against the temp dw. This will catch nasty errors like a column being changed from 80 to 120 characters and a DataWindow was missed.

        If you’re concerned whether the linkage service works correctly you can write tests for it. As long as that service has been around I don’t see any payoff in writing tests for the linkage service unless you’re planning to make changes to it.

        If you want to test whether your objects are using the linkage service correctly you’ve got some work to do. It’s straightforward to inherit from n_cst_linkage and make a mock for it, but in order to use the mock you’re going to have to refactor your window so that the DataWindows are shared from DataStores in an NVO, which also has your code for the linkage service, transaction object, etc.. Because inv_linkage is Public in n_ds and u_dw, your test can plug in the mock and test that the expected calls are made to the linkage service.

  8. Hi Frank,
    we use PowerBuilder 12.5 Classic. If the PBUnit used by anyone of a comprehensive application development? Do you know someone or someone reading this by chance?

    • There are over 3200 asserts in my test run. That’s not comprehensive for the monster of an app we’ve got but among the code I have covered is complex cross validation logic that historically gave us fits. Get one tiny thing wrong in hundreds of validation rules and the user can’t save because there is no valid combination of values. We typically get a few validation changes in each release and the changes can cause conflicts that get the user stuck with no valid choices. A couple years ago I was 2 weeks from release and the validation wasn’t working. Dozens of rules had changes and the test team kept finding new ways the user could get stuck.. I realized I would never finish on time by changing code and running the app to re-test. There were too many combinations. I set up PBUnit and started writing tests and was quickly able to show that some of the rules conflicted and others weren’t implemented properly, including rules that hadn’t changed in years. I got the business analysts to correct the conflicting rules and fixed the other errors. The release was on time and that validation code hasn’t been a problem since.

  9. Hi Frank,

    Let me ask you a question is there a way using PBUnit to test a CRUD GUI interface where the insert and updates are made directly to DW (Values are entered in DW Fields intead of collecting them in Objects like SLE)and assert the values for each field? Could you help with this? I have been diggin on Unit Test for PB, but if I cannot do it directly on DWs it makes no sense for me.. I should re code the whole application. I appreciatte your help. Thanks in advanced.



  10. Hi Frank,

    In PbUnit Testing Tool ,Could we not able to set the values for the datawindow control?
    Is there any way to proceed? I will give my sample scriptings below,
    iw_number_desc.dw_search.object.nbr_qty[1] = 25.
    Since I am getting Null Object referance error,even though the object gets assigned, but the row is not getting inserted.
    But if we try the same in datastore the row gets inserted?

    Could you please give me a solution of how to proceed further ?.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s