quinta-feira, 28 de abril de 2016

Simulando códigos APEX para testes com Test.isRunningTest() - SFDC

Em algumas situações (talvez até raras), temos dificuldade ou até mesmo impossibilidade de gerar uma massa de dados que nos permita cobrir (com testes unitários) o nosso código Apex, no Salesforce. 

Em casos como esse, seria ideal fazermos um código "fake" apenas para nossa classe de testes unitários e o código real para nossa aplicação. Para essas situações, usamos o método estático isRunningTest, da classe Test. Ele retorna true, se estiver sendo executado apartir de uma classe de testes e false, se for apartir de uma aplicação normal. Com o isRunningTest, portanto, é possível verificar, em meio à nossa lógica de negócio, se vamos usar um código real ou apenas para testes.

Um exemplo clássico é quando precisamos acessar o PriceBook padrão (StandardPriceBook). Como não conseguimos criá-lo em uma classe de testes, para ser usado na classe de regra de negócio, usaremos uma combinação do isRunningTest com getStandardPricebookId, da classe Test (que já conhecemos melhor através do post Criando registros do catálogo de preço (PriceBookEntry) padrão em classes de teste Apex). Veja a seguir como ficou meu método em uma classe de regra de negócio:


 id idPriceBook = null;  
 if (Test.isRunningTest())  
      idPriceBook = Test.getStandardPricebookId();  
 else {  
   PriceBook pb = [SELECT id FROM PriceBook2 WHERE IsActive = true AND IsStandard = true];  
   idPriceBook = pb.id;  
 }  

Perceba que quando esse código for chamado por uma classe de testes, irá executar o IF, porém, se for chamado por uma execução comum, irá executar o ELSE. E dessa forma conseguirei cobrir completamente a minha classe de negócio.

E esse mesmo código, de forma mais resumida:


 id idPriceBook = Test.isRunningTest() ? Test.getStandardPricebookId() : [SELECT id FROM PriceBook2 WHERE IsActive = true AND IsStandard = true][0].id;  


Por hoje é só!



sábado, 23 de abril de 2016

Lendo parâmetros de uma URL no Salesforce

Esse mais um post rápido e simples para exemplificar como ler os dados passados pela URL, em páginas Visualforce ou classes controller Apex. Para contextualizar estamos falando da QueryString, que são aqueles parâmetros que passamos em uma URL:

 https://c.cs20.visual.force.com/apex/CotacaoAceite?Id=01pm0000000Bf0q&Valor=3&Outros=Teste  

Nessa URL acima, o que seriam os parâmetros?


Parâmetro Valor
ID 01pm0000000Bf0q
Valor 3
Outros Teste

*O símbolo & é entendido com um separador entre os parâmetros.

Bem, agora vamos ao que interessa. Como ler os valores em uma página Visualforce ou em uma classe controller Apex do SFDC?

Visualforce:


 {!$CurrentPage.parameters.ID}  
 <br/>  
 {!$CurrentPage.parameters.Valor}  
 <br/>  
 {!$CurrentPage.parameters.Outros}  
 <br/>  


Apex:


 Id idItem = ApexPages.CurrentPage().GetParameters().get('id');  
 String valor = ApexPages.CurrentPage().GetParameters().get('Valor');  
 String outros = ApexPages.CurrentPage().GetParameters().get('Outros');  


Bem, é isso aí!




quarta-feira, 20 de abril de 2016

GUID no Salesforce

Hoje irei compartilhar uma pequena função Apex para gerar um código GUID no Salesforce. GUID significa Globally unique identifier. Em português Indentificador global único. Isto é, uma código único que é gerado para identificar alguma coisa. Normalmente é usado para identificar registros em sistemas diferentes, em processos de integração. Bem, o que vamos gerar a seguir ficará assim:


 4b033118-86a6-8941-c6e2-ad1015509c6c  

O SFDC, por padrão, diferente de outras plataformas de desenvolvimento, não possui uma classe padrão para gerar os GUID. Após algumas pesquisas encontrei em alguns fóruns um código simples e interessante, que compartilho a seguir:


 global class Guid{   
   global static String generate(){   
     Blob b = Crypto.GenerateAESKey(128);  
     String h = EncodingUtil.ConvertTohex(b);  
     String guid = h.SubString(0,8)+ '-' + h.SubString(8,12) + '-' + h.SubString(12,16) + '-' + h.SubString(16,20) + '-' + h.substring(20);  
     return guid;  
   }  
 }  


Li também que esse código não seria tão perfeito, pois poderia gerar GUID repetidos. Dessa forma, fiz a classe de teste a seguir e não constatei nenhum código repetido:


 @isTest  
 private class GuidTest{  
   static testMethod void test(){  
     boolean erro = false;  
     Set<String> lista = new Set<String>();  
     for (integer i = 0; i < 100000; i++){  
       String uid = Guid.generate();  
       if (lista.contains(uid)){  
         System.debug(i);  
         System.debug(lista.Size());  
         System.debug('GUID: ' + uid);  
         erro = true;  
         break;  
       }  
       else  
         lista.add(uid);  
     }  
     System.assert(!erro, 'A classe GUID gerou um valor duplicado!');  
   }    
 }  

Veja que gerei cem mil UIDs e nenhum duplicou. Me pareceu bem confiável! Porém, se alguém encontrar alguma falha, comente aqui no post. 

Por hoje é só!




terça-feira, 19 de abril de 2016

Habilitando envio de e-mails na Org Salesforce

Uma situação corriqueira que nos deparamos ao inciar os trabalhos em uma nova Org Salesforce, é que alguns e-mails que programamos ou configuramos o envio, acabam não sendo enviados. 

Acesse a opção de Configuração da sua Org e siga o passo-a-passo para habilitar o envio de e-mail:



Menu Administrar / Administração de email / Capacidade de entrega.

Em seguida, marque a opção "Todos os emails" na opção Nível de acesso.




Por fim, basta clicar em Salvar para que sua Org envie emails normalmente! 



quarta-feira, 6 de abril de 2016

Tamanho médio de um registro no Salesforce

Esses dias me deparei com uma situação onde a ORG de um dos nossos clientes estava quase atingindo o limite (em MBs) do espaço disponível na ORG. Ao acessar a opção de "Uso do armazenamento" (Menu: Configurações/Gerenciamento de dados/Uso do armazenamento) verifiquei em um dos objetos que aproximadamente 50 mil registros consumiam 100 mb de espaço. Ao verificar outros objetos, tanto maiores como menores, a proporcionalidade era a mesma. 

Resolvi realizar algumas pesquisas e encontrei diversos artigos e pessoas comentando exatamente o mesmo. Para cada registro (na grande maioria dos casos) no Salesforce, consome-se 2KB de espaço na sua ORG.

É necessário olhar o lado positivo de tudo, certo? Então, a parte positiva é que fica fácil calcular quanto de espaço será necessário, em cada novo projeto, expansão ou para política de expurgo. 

O ruim é que se consome muito espaço para registros pequenos. Em caso de objetos apenas para relacionamento (N-para-N), por exemplo, é um espaço muito grande por registro.

Vi uma ideia cobrando uma solução para o problema. Mas ainda está pouco votada. Quem quiser apoiar a iniciativa: Charge fairly for storing small objects. Eu apoiei!