function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Zoom-ZoomZoom-Zoom 

Test-Drive Development (TDD) with apex?

I was wondering if anybody has any experience with doing Test-Drive Development (TDD) with apex? I've started experimenting on my own but was curious to know if people have developed some TDD practices specific to Salesforce.

 

For instance, TDD's point is to write the tests before writing any code, but Salesforce statically typed language doesn't allow to write some code that calls a class or method that doesn't exist yet. Should one write a class stub just to be able to save the test code? Something else?

sfdcfoxsfdcfox
Test Driven Development is indeed a useful model for programming, since it lets you assert what the logic should do before you ever write a single line of that logic. Many compile-time languages don't allow missing classes or class members, and thus expect a minimum amount of framework in place before you can compile a test at all. This is "good" in the sense that the language is asserting that there are no dangling pointers, etc.

Apex Code is no exception to this model. All code has to resolve to valid constructs before you can save a single line of code anywhere. This forces a lock-step process that developers must adhere to in order to successfully run tests. You can, however, delete methods later, but your test won't run at all, making this venture pointless.

Given the nature of Apex Code, I would imagine that a TDD-oriented approach to Apex Code would involve writing stubs, writing tests, then completing the stubs until the tests no longer fail. I typically write the test methods and code in tandem, when possible, as a sort of double-check. It's usually more difficult to write the same logic wrong twice, since writing test methods forces the developer to think about the implementation.
Zoom-ZoomZoom-Zoom

Thank you for your feedback.

 

Personally, I've found that the best way to motivate myself to write tests is to tie them to the user requirements - and to let users see what the tests do.

 

This is why I'm trying to see if I can come with an apex version of Cucumber (an automated testing tool for Ruby) that can be somehow usable.

sfdcfoxsfdcfox

I've thought about this, too. Unfortunately, I don't think I have the time to actually do this. I'd be glad to provide some feedback if you have any ideas on how you might do it. We need better testing, and I think it'd be a great project.

Zoom-ZoomZoom-Zoom

I've actually started writing my own Cucumber implementation called Pickle. It's still a draft of course, but can already handle a scenario like:

Given the following Users exist:
1|Joe Smith

Given the following "Accounts" exist: Account Id|Account Name|Owner Id 2|Foo Inc.|1 Given the following "Cases" exist: Case Id|Account Id|Owner Id|Subject|Case Origin|Escalated 3|2|1|This is a test|Web|true Given I am on page "My VisualForce Page" When I set "My Field" to "Random Value" and I click on "Update" Then "result" should contain "OK" and "numeric Field" should be >= "5"
sfdcfoxsfdcfox
Looks interesting. Not sure I could be of any help, but I'd be willing to offer any assistance I can.
Zoom-ZoomZoom-Zoom

I'm OK about handling the development part. However, there are a couple of ways you can help:

  • Is this the type of tool you would use as it is? If not, what is missing?
  • Do you know of anybody else who could be interested? If so, could you ask them to check the tool out?
  • One of the things I'm working on is a class which serves as repository of scenarios, so they can be shown to end users through a VF page. The challenge is however to verify the scenarios are actually part of some tests and not added just for show. My current approach involves parsing the test classes code (ApexClass SObject), but I am open to suggestions for a better approach.
Zoom-ZoomZoom-Zoom

Also, do you happen to know if there is a way to dynamically read the fields of an Object? I know how to do that with an SObject, but not an Object. A System.debug() on an Object however displays its fields, so the information is somewhere.

sfdcfoxsfdcfox
Q) Is this the type of tool you would use as it is? If not, what is missing?

A) I'd probably prefer to use this either in a browser, an IDE, or even a CLI project. As a pure Apex Code function, it'd be far too limited, given the lack of proper reflection in Apex Code. The concept is definitely sound though.

Q) Do you know of anybody else who could be interested? If so, could you ask them to check the tool out?

A) Not directly, but I'll probably post something about it on my various social networks and direct them here.

Q) One of the things I'm working on is a class which serves as repository of scenarios, so they can be shown to end users through a VF page. The challenge is however to verify the scenarios are actually part of some tests and not added just for show. My current approach involves parsing the test classes code (ApexClass SObject), but I am open to suggestions for a better approach.

A) Parsing the Apex Code would be the best way to accomplish this, I think. For performance reasons, you'll probably still need to move this logic to something client-side (e.g. JavaScript), or you'll run into script limits for large classes.

Q) Also, do you happen to know if there is a way to dynamically read the fields of an Object? I know how to do that with an SObject, but not an Object. A System.debug() on an Object however displays its fields, so the information is somewhere.

A) Inside Apex Code, the only reliable method would be to JSON.serialize, then JSON.deserializeuntyped into a map; you can then read the keys/values directly. Outside of Apex Code, you'd have a much easier time of it.
Zoom-ZoomZoom-Zoom

Thank you for your feedback. Using a scenario in an IDE is an interesting idea. But that would mean running it "live", outside of Salesforce tests, wouldn't it?

 

I thought about coding it as a pure Apex solution so that 1) it can be used in Salesforce test methods (and benefit from the fact the transaction doesn't get committed) and 2) one needs anyway to provide some apex code to bind to one's methods and VF actions.

sfdcfoxsfdcfox
Actually, I was thinking more like a Pickle to Apex Code compiled step. You don't have to write test methods directly, you instead let Pickle do that for you. This would give the natural language appeal with non-committing test transactions.
Zoom-ZoomZoom-Zoom

Ah, interesting. I hadn't thought of generating test code. You lose the dynamic aspect of a script (if you change the script you need regenerate everything and manually add some of your custom code) but you wouldn't have to jump through hoops to determine what functions to call in the code.

c_jonasc_jonas
I feel TDD is not realistic on Salesforce.  The key issue is that Salesforce tests are SLOW!  With TDD you need to be able to execute your tests almost instantanously.  Salesforce can take minutes to run a single test with only a couple lines of code.