22

Scenario: Production org has sufficient code coverage with unit-tests. Someone adds validation rule(s) which cause the tests to break. Minimum 75% code coverage is no longer there. We come along to add new code (were not involved in the orginal code). When we go to deploy our code which itself has sufficient coverage the deployment fails due to the newly added validation rules breaking the tests on the legacy code.

Options here are

  1. Review all the legacy code written by a third party and update it and its tests so it handles the newly added validation rules - not really viable in some cases, neither the client nor ourselves want that expense.
  2. Manually disable the validation rules which are breaking the legacy code unit-tests for the duration of the deployment - not ideal, but the route I've been forced to take on occasion.
  3. ???
17

I have seen a solution that uses a Custom Setting of ValidationRuleEnabled.

ALL validation rules set up have the && $Setup.CustomSetting__c.ValidationRuleEnabled__c added.

When you want to deploy any code then the administrator changes the Custom Setting to FALSE, deploy the new code; don't forget to re-enable the Custom Setting!

Again this is not ideal as the 'legacy' code should be updated to accommodate the new validation rules; ideally at the time of creating the new validation rules (but who checks code coverage after making a small change like a validation rule?)

  • I quite like this, it does mean a hit to apply it to all validation rules initially, but once in place and all admins know to add it to any new validation rules it would help greatly. – David Gillen Aug 1 '12 at 13:18
  • 1
    The thing about custom setting is that it is treated as data and not as metadata. That means that every time you spin a new sandbox you have to add this custom setting or you won't be able to deploy any validation rule to it. – Anup Aug 1 '12 at 14:49
  • Accepted this answer as it best suits my needs, even though option 1 is probably ideal, in the real world supporting thousands of lines of code/tests deployed by previous suppliers is not usually an option. – David Gillen Aug 2 '12 at 9:58
6

The use of $Setup.CustomSetting_c.ValidationRuleEnabled_c is very creative.

I typically handle this by making sure that any records I create using "UNITTEST" in the Name field and then check for NAME != "UNITTEST" in the validation rule.

The issue with legacy code still exists. Ideally, Salesforce.com will come up with a simple function for ISUNITTEST().

5

I vote for #1 - update all existing code written by other people, etc. Why? It's very clean and makes sure that the code still works with those validations in place or not. What happens if you have a validation rule that requires a field if X,Y,Z and your Apex code had not previously assumed this to be true. In fact what if your Apex code assumed that the field would be blank if X,Y,Z? If you bypass the validation rule the Apex code would still pass it's tests, but in production when the field was filled in when X,Y,Z the Apex code would break.

Edge case to be sure and for the most part we all agree that it's painful when new validation rules break your or past tests so I'd bet most people do #2 (disable it) and then when they have time go back and do #1 (clean test code).

One thing that can really really help is if you create a 'TestDataGenerator' class that is responsible for creating all of your test data, then you only need to modify the code there as opposed to everywhere. Of course this doesn't help for your unmanaged packages installed off the AppExchange, but at least helps you with your code.

If you really want to bypass the validation rules what I typically do is check the user's profile. Typically you can set it up so System Admin or a custom profile "Apex Admin" doesn't have to have the validation apply. Much like the CustomSetting, however if you use the custom setting during the deployment no user has the validation apply whereas with a check to profile only the user(s) with that profile can bypass the validation.

Looking forward to hearing more folk's thoughts on this one!

  • I am in agreement that the first option, to update all legacy code, is the ideal scenario. Unfortunately I've come across real world instances where there were 10,000s of lines of legacy code and associated unit tests which were failing due to new validation rules. This code was written by a third party who was no longer present. The cost of updating all this unknown code what more than prohibitive. – David Gillen Aug 1 '12 at 15:44
  • I prefer the use of a specify no-validation profile rather than turning validation off for all users. – Born2BeMild Aug 2 '12 at 11:55
  • Lol, just answered this and you'd already put in my two cents for me. Hope you're doing well caleb – Ralph Callaway Nov 8 '12 at 2:51
3

I've seen a couple approaches that have all worked well in certain scenarios.

1) Smarter Validation Rules - For non critical validation rules give tests a hook to disable them (test user's profile, custom setting, etc.)

2) Build a Utility Class for Data Creation - Class is responsible for returning an object that can be saved and nothing more. All tests use this as a starting point. If a new validation rule breaks your test you only have to update one place.

3) Turn off the Validation Rules for Deployment - Not ideal, but it works. Can be scripted pretty easily (download all validation rules to eclipse, save to source control, find and replace to inactivate them, save, deploy, revert)

If you're stuck with a ton of legacy code option 3 is the only one that seems viable to me. But for new code, make sure whoever builds your code follows #2. And if you're considering building code, take into account that you'll need a developer to maintain it.

Finally, look into setting up an automated test running framework. At least then you'll know right away when you're tests break as opposed to the day a big deployment is supposed to go live.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.