Tuesday, January 7, 2014

Salesforce1 list views and Flexipages

Issue: List Views are not displayed by default in Salesforce1 tabs

Part of the Salesforce1 mobile app is a design decision that makes visible in the mobile app only the list views that a user had previously run in the Salesforce.com application.  We were caught by surprise with this "feature" when we rolled out a new mobile app on Salesforce1.  Our mobile users didn't see any of the list views we had created for them in the main application, because they are primarily mobile users, and it was only through trial-and-error did we discover what was going on.  We were able to corroborate our experience when we saw this idea.

Some of the possible workarounds we explored:

Pinned List Views:
While we knew that this would be self-correcting over time, we thought about some alternatives that were mentioned in that thread.  One suggestion was to use "pinned list views", or PLVs, which I had not heard of before.  PLVs were introduced in the Winter 14 release as part of the Service Cloud console. We're not Service Cloud users so it was not a viable workaround for us.

Flexipages:
The other idea, that was suggested was to implement "Flexipages".  Flexipages were introduced in the Salesforce1 developer guide, chapter 15, as "a middle ground between page layouts and visualforce pages".  After working with these, I'm not sure I agree.  I'm not even sure I'd say that this feature isn't a beta as the procedure for developing and deploying feels half-baked.  Here are some of the key takeaways:

1. There is neither a gui section in the Setup menu for flexipages nor a way to create a flexipage using the developer console.  I did my "dev" with Notepad.  I took the example xml and changed it for my custom object in my text editor and saved it as .xml.

2. My flexipage just need two things: an "All" items list view and a "Recent" items list view.  The docs are unclear how you achieve this but basically you reference your application's list views by name.  For example, if you have a list view in Salesforce.com with a Name "All_Records", your flexipage.xml should have something like this:

<componentInstanceProperties>
<name>filterName</name>
<value>All_Records</value>

</componentInstanceProperties>

3. According to the docs, the flexipages are deployable from the force.com ide.  I upgraded my ide and did not see any reference to flexipages.  Could be an ide update issue but for the sake of time I ended up using workbench to deploy my package.  Just zip up your package and include an updated package.xml like what is described in the api documentation:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <fullName>Travel, Inc.</fullName>
    <types>
        <members>TravelIncFlexiPage</members>
        <name>CustomTab</name>
    </types>
    <types>
        <members>TravelIncFlexiPage</members>
        <name>FlexiPage</name>
    </types>
    <types>
        <members>TravelIncQuickActions</members>
        <name>QuickAction</name>
    </types>
    <version>29.0</version>
</Package>

4. It took a few tries for me to deploy the package in workbench but when it finally went through, the last few steps to expose the page in the Salesforce1 app were straightforward.  Just add a flexipage tab and then add the tab to your mobile navigation as described in the developer guide.

5. Any updates to your flexipage require you to reload your flexipage xml.  Ugh.  Hopefully you remember where you backed it up and be sure to buy your admin a beer as they're going to hate deploying this.




Monday, December 16, 2013

Apex Test Methods - SeeAllData

One topic that I want to touch on is the SeeAllData attribute.  I thought to include it in my other post about test methods but decided to give this one it's own space.  First, let's get a definition on it:

***
Starting with Apex code saved using Salesforce.com API version 24.0 and later, test methods don’t have access by default to pre-existing data in the organization, such as standard objects, custom objects, and custom settings data, and can only access data that they create. However, objects that are used to manage your organization or metadata objects can still be accessed in your tests such as:
User
Profile
Organization
AsyncApexJob
CronTrigger
RecordType
ApexClass
ApexTrigger
ApexComponent
ApexPage
Whenever possible, you should create test data for each test. You can disable this restriction by annotating your test class or test method with the IsTest(SeeAllData=true) annotation.
Test code saved using Salesforce.com API version 23.0 or earlier continues to have access to all data in the organization and its data access is unchanged.

***

I've seen and heard many people claim that setting this attribute to true was a bad practice.  Go ahead and google it.  You'll find plenty of well-intentioned people telling you that you should never (or very rarely) set it to true and warn you like they were saving you from some kind of doom.

I say that there are plenty of reasons to use it and removing this from your tool set, puts you at a disadvantage.  Let's look at a couple examples of where I see some utility:

  • Existing org data
    • Volume
    • Quality
  • Custom settings
Setting SeeAllData to false (or accepting the current default), limits your test methods from existing org data. So for example, if you were to query for an existing account and set a field value in your test method, you'd end up with a query exception.  If you were the developer of a managed package, you'd probably be smart enough to recognize that this scenario and that your account doesn't exist in your customer's org, so you'd need to create a new account in your test methods.  In this case, SeeAllData = false, makes sense because you cannot assume that your test data exists in someone else's org.

If you were the developer of your company's internal Salesforce instance, your perspective and use cases are likely to be different. Imagine you've created a vf page that aggregates some account data.  For a page that does a lot of soql queries, you may be concerned about performance or governor limits.  If your org had millions of accounts, you could make your test methods try to simulate your account data volume, but it might be smarter to make use your existing data in your full sandbox also.  Running apex tests for both new and existing data, you'll be more confident in how your application behaves in production.  

Data quality is another place where setting SeeAllData = false may leave you vulnerable.  Let's say your org's history was something like this:
  1. In January, your users started using opportunities
  2. Later in March, they created a validation rule to make a field required on opportunities
  3. In June, you were asked to come in and add a trigger to activities to automatically update the related opportunity
If you were using SeeAllData = false, your test methods would create a new account and opportunity, create a related Task, and successfully assert that the Opportunity was updated by your new trigger.  Your test opportunity would have been created with all of the required data and your trigger would pass your unit tests.  However, the trigger would fail in production, perhaps unexpectedly, because you didn't know that there were January opportunities that had not been updated after the validation rule was introduced.  If you were using SeeAllData = true, you may have caught this data inconsistency and been prepared to handle the exception cleanly.

I think custom settings are another place where I'd look to use the SeeAllData.  In much of my apex code, I try to make the code flexible through a custom setting.  So, for example, if I am integrating via an http callout, I'd try to put the endpoint url in a custom setting.  Using SeeAllData = false, I could succesfully deploy to production without ever setting up the custom setting because my test methods create the custom setting. However, using SeeAllData = true, my test methods would fail because the custom setting had not been created in production.  This allows me to be sure that my dependency is in place before bringing users back into the system.  

So, there you have it.  SeeAllData = true can be your friend.  It's like bacon - plenty of people will tell you to avoid it, if you want to live.  But I say a little bit in your life can be delicious.
  

Deep Thoughts on Apex Test Methods

You're good enough.
You're smart enough.
You can write a good apex test method.

I just completed a major rewrite of all test methods for a client and while it was painful at times, I think it puts them in a position to extract some value from what was previously just a production deployment hurdle. Trust me, I'm not yet a full test-driven-development convert but I do believe that you can help your business automate some testing, and maybe even save some cash, if you take the time to think about your testing and apply it to your test methods.

You get better at the things you do over and over and writing good test methods is certainly something you can expect to have plenty of opportunity to practice.  There are some great resources out there to be sure you are repeating good habits. I'd start with Dan Appleman's Advanced Apex book as he has some great ideas for test class writing. Some other articles that I think are helpful and instructive are:

http://jessealtman.com/2013/09/proper-unit-test-structure-in-apex
http://wiki.developerforce.com/page/How_to_Write_Good_Unit_Tests

With this recent rewrite effort, some of the good practices I've incorporated are:

  • Moving test methods from functional classes into separate Test Classes
    • This allows you to decouple your tests from your functional classes, which excludes your tests' ability to reach private methods.  This will give you some flexibility with refactoring your code without being tied down by your test methods.
  • Asserting results
    • While you may achieve the 75% goal of code coverage, your tests will have little/no value if you are not actually checking expected versus actual results.  As a managed package developer, you'll also get flagged during the security review if you are not asserting your results. 
  • Centralizing and standardizing helper utilities
    • Like other apex you write, you should try to encapsulate where you can and use helpers to minimize the effort in testing various permutations of data against your code.
  • Testing negative scenarios
    • This is another area where you can get some value out of unit testing.  While it may take 80% of your effort to identify and code these, it's going to yield lots of value in improving your code and confidence in your code handling atypical scenarios.
  • Testing as an end user
    • Unfortunately as developers, we are system admins and almost everything we test works as expected because we don't have to deal with sharing or role hierarchy or object/field visibility. However, in the real world, our users are almost never system admins, so testing as a system admin makes no sense.

This is certainly not the complete list of best practices, but it's a good start.

As with other things in Salesforce, there is some room for improvement with the execution of unit testing in the application. In particular, I'm still frustrated by what Jeff Douglas calls the "black art".  Like Jeff, I've come across some peculiar behaviors that can be maddening.  For example, if you are testing a trigger and need to create a user and then test the dml, there's a pretty good chance you're going to get a mixed DML exception.  What is maddening, however, is that the error will not be caught in the force.com ide.  Oh, and you can deploy to production with this too!  The only thing keeping me sane was knowing that someone else noticed this too:



And aside from the nonsense of trying to estimate your code coverage in any of the tools out there, it would be nice if the test classes had the code coverage estimation like the functional classes for those of us separating them:


And don't get me started on the new test execution screens.  Aside from queuing your tests, they provide no value!

I think there is plenty to like about putting some effort into doing proper unit testing in Salesforce.  I'm sure if you build in the time to your sprints/plans, it will pay dividends in the long term.  Just be sure you approach this with a good sense of humor.


Wednesday, November 20, 2013

Traffic Nightmare @ Dreamforce

This is incredible..last year, the SF Giants were in the playoff hunt so downtown was already jamming. I can't even imagine trying to drive anywhere with over 140k registered attendees this year:

Monday, November 18, 2013

Drink the Kool Aid, It's DreamForce Season Again!

Salesforce1 appears to be the big announcement this year.  I just watched this video that Salesforce published and while the music and voice over are great, I don't understand a thing about what is being announced.  If you can make sense of this video, please share in the comments.


Wednesday, November 13, 2013

A Bug!

It's not often that I come across a real bug with Salesforce's apex or visualforce platform.  Most often there are limitations or shortcomings that you have to workaround.  Recently, I had to make an urgent change to a trigger and it's associated test class.  However, when I attempted to comment out a line in my test class, I got the following error in the editor when I tried to save:

java.lang.reflect.InvocationTargetException

When I attempted to make the same change in the developer console, I got another error:

 An unexpected error has occurred. 421011484-16071 (1420197083) for deploymentId=1drJ00000002FDxIAM If this persists, please contact customer support.


Fortunately, I was able to still deploy my code without the test class change but I opened a case anyway and after waiting a few days for a reply, was told that it was a known issue.  The instructions from developer support were:
  • Please clear Test results and try to save the code:
    • From Setup, click Develop | Apex Test Execution |View Test History | Clear test results. 

However, even before I did these actions, I tried to update the test class again and surprise!  no errors. So, something fishy is going on... Support wants to close the case but I'm inquiring for additional details.  Will keep you posted.


**Update Nov 13**

Salesforce has responded and indicated that it was a bug but has been fixed.  Details here: https://success.salesforce.com/issues_view?id=a1p30000000T17j

Friday, November 8, 2013

Workflow and User Permissions

Q: Do workflow rules run as the user or do they run as the system?  For example, if you had a sales team associate update an opportunity and there was a workflow that fired on any opportunity edit, would the workflow update a field that the user did not have profile (or permission set) permission to update?

Q: If the workflow action reassigned ownership to another user, would it execute the ownership change despite the user's system permission of Transfer Records as false?

Q: If the workflow action changed the record type to a value, would it change the record type if the user's profile did not have access to the specific record type value?

***

My initial reaction was that workflow would run as the logged in user and would obey the user's profile and permission sets.  However upon testing, what I found was that workflow runs as the system and does not honor the user's profile or permission.  So, for the 3 questions above:

  1. Workflows run as the system and would update a field that the user did not have profile/permission set access to update
  2. Workflows will execute ownership changes on behalf of users who do not have permission to directly change the ownership
  3. Workflows will change record types in spite of profile-specified record type access.