This brief post is a continuation of the prior one and discusses the possibility of generating tests from profile XML(s), rather than using SOQL. Note: This is basically a proof of concept that relies on reading a directory of profile xml files, then parsing the field accessibility values based on a target Object. The fields gathered from the profile xml, are not exhaustive and thus may not result in passing tests. See the last post for a more accurate solution.
This script “generateProfileUnitTests.py” was created in Python 2.7, it will generate a sample Salesforce unit test named “generateProfileUnitTests.cls”
#!/bin/python """ python generateProfileUnitTests.py -o 'Contact' -d 'C:\Salesforce\profiles' """ import sys import xml.etree.ElementTree as ET import argparse from os import listdir from os.path import isfile, join import re parser = argparse.ArgumentParser() parser.add_argument("--sobject", "-o", type=str, required=True) parser.add_argument("--profiledirectorypath", "-d", type=str, required=True) args = parser.parse_args() sobject = args.sobject filetemplatePre = """ @isTest public class ContactObjectTest {{ static String writeFieldName = 'PermissionsEdit'; /** object = Contact profile = System Administrator **/ private static void runProfileTest(String objectName, String profile, Map<String, Map<String, Boolean>> expectedPerms) {{ Boolean success = true; try {{ List perms = [SELECT Id, Field, SObjectType, PermissionsRead, PermissionsEdit FROM fieldPermissions WHERE SObjectType = :objectName AND parentId in ( SELECT id FROM permissionSet WHERE PermissionSet.Profile.Name = :profile)]; Set nonExpectedFieldsFound = new Set(); // Go through actual perms and make sure they exist if expected for(FieldPermissions perm : perms) {{ try {{ Map<String, Boolean> expectedPerm = expectedPerms.get(perm.Field); System.assertEquals(expectedPerm.get(writeFieldName), perm.PermissionsEdit, 'Permission named ' + perm.Field + ' is ' + perm.PermissionsEdit + ' but expected ' + expectedPerm.get(writeFieldName) ); // Should also create a copy and remove (to assert exact fields?) }} catch (NullPointerException e) {{ nonExpectedFieldsFound.add(perm.Field); // Error is 'Attempt to de-reference a null object' System.debug('Found a field that was not in expected permissions: ' + perm.Field); success = false; }} }} System.assertEquals(0, nonExpectedFieldsFound.size(), 'Found Read only fields in ' + objectName + ' for ' + 'profile -- ' + profile + ' -- that were not in expected set: ' + nonExpectedFieldsFound); }} catch (Exception e) {{ System.debug('Failed profile field test ' + e.getMessage()); success = false; }} finally {{ System.assert(success); }} }} static Map<String, Boolean> createPerm(String writeName, Boolean value) {{ Map<String, Boolean> perm = new Map<String, Boolean>(); perm.put(writeName, value); return perm; }} /****************** PROFILE FIELD ACCESS TESTS *****************/ {tests} }} """ fileTemplateInsertTest = """ static testMethod void test{sobject}ReadWriteFields{profileFormatted}Profile() {{ runProfileTest('{sobject}', '{profile}', {expectedFieldsMethod}()); }} """ fileTemplateInsertExpectedFeilds = """ static Map<String, Map<String, Boolean>> get{sobject}{profileFormatted}Fields() {{ Map<String, Map<String, Boolean>> {sobject}Fields = new Map<String, Map<String, Boolean>>(); {insertExpectedFeild} return {sobject}Fields; }} """ fileTemplateInsertExpectedFeild = """ {sobject}Fields.put('{fieldName}', createPerm(writeFieldName, {editFieldAccess}));""" testFile = '' tests = '' for f in listdir(args.profiledirectorypath): if isfile(join(args.profiledirectorypath, f)): tree = ET.parse(join(args.profiledirectorypath, f)) profileName = f.split('.')[0] expectedFeild='' for child in tree.getroot(): if 'fieldPermissions' in child.tag: # Get field fieldName = child.find('{http://soap.sforce.com/2006/04/metadata}field') if sobject + '.' in fieldName.text: editable = child.find('{http://soap.sforce.com/2006/04/metadata}editable') # readable = child.find('{http://soap.sforce.com/2006/04/metadata}readable') expectedFeild+=fileTemplateInsertExpectedFeild.format(sobject=sobject, fieldName=fieldName.text, editFieldAccess=editable.text) profileFormatted=re.sub('[^a-zA-Z]+', '', profileName) insertExpectedFields=fileTemplateInsertExpectedFeilds.format(sobject=sobject, profileFormatted=profileFormatted, insertExpectedFeild=expectedFeild) insertTest=fileTemplateInsertTest.format(sobject=sobject, profileFormatted=profileFormatted, profile=profileName, expectedFieldsMethod='get' + sobject + profileFormatted + 'Fields') tests+=insertExpectedFields tests+=insertTest testFile = filetemplatePre.format(tests=tests) f = open('generateProfileUnitTests.cls', 'w') f.write(testFile) f.close