요즘 자꾸 발생하는 문제인데

인증이 자꾸 실패하면서 작업을 진행시키는 일이 발생했다.

 

이전에는 apex package를 지우고 설치한 다음 인증하거나

재부팅 후 하는 등의 작업을 하다 보면 갑자기 되는 일들이 있었지만

에러코드 위에 경고를 자세히 보니 더 이상 지원하지 않는다는 문제였다.

 

기존의 방식은 아래의 코드 형태였는데

sfdx force:auth:web:login --setalias vscodeOrg --instanceurl https://login.salesforce.com --setdefaultusername

수동으로 아래와 같이 alias, url, default 부분을 수정하니 정상적으로 처리되었고

sfdx org:login:web --alias vscodeOrg --instance-url https://login.salesforce.com --set-default

더 짧은 대체어를 통해 아래와 같이 수정할 수 있었다.

sfdx org:login:web -a vscodeOrg -r https://login.salesforce.com -s

 

id를 가져오는 작동 방식이 ApexPages.currentPage().getParameters().get('id'); 형태였기 때문에

ApexPages.currentPage().setParameters().put('id', ‘value’);로 넣었는데 에러가 발생했고

문제를 확인해보니 put 또한 getParameters() 내부 메서드로 동작하고

setParameters는 존재하지 않는다고 한다.

 

통화등의 기준이 되는 Currncy등의 값을 수동으로 넣기는 애매하다고 생각했는데

{!$Label.firstrun_helptext}를 사용할 경우 접속자의 위치(또는 언어 세팅)에 맞게 설정되기 때문에

좋다고 하는데 작성하며 생각해보니 금액은 그대로고 금액 기호만 바뀌면 이상할 것 같았는데

제로도 동의하시며 해결책이 궁금하다고 하셔서 고민해보니

다중통화정책이 있고 지원하지 않는 국가는 usd등으로 대체한 다음

해당 국가의 통화에 맞는(환율에 맞게 세일즈포스에서 자동 조정된) 금액을 불러올 수 있을 것 같다.

 

잘 진행되던 도중 인증 만료라는 이상한 에러가 자꾸 발생하며

deploy가 진행되지 않아서 원인을 파악해도 정확한 원인은 알 수 없었다.

 

껐다 키는 것도 의미가 없고 저번처럼 다시 또 패키지를 재설치해야 하나 생각했다가

끄지도 않고 하던 중에 이렇게 세션 만료가 될 정도면 제대로 된 해결책을 찾아야겠다고 생각했고

sfdx logout이라는 기능을 발견할 수 있었다.

sfdx force:auth:logout -u username@org.com.dev

 

다만 logout을 하고 재로그인을 한다고 되는 것은 아니고

로그아웃 후 vscode를 다시 시작하고 인증을 진행하면 정상적으로 작동했다.

 

오늘따라 특히 인증 문제가 자주 터졌는데 아래의 두 코드만 기억하면 될 것 같다.

로그아웃 = sfdx force:auth:logout -u username@org.com.dev

로그인 = sfdx org:login:web -a vscodeOrg -r https://login.salesforce.com -s

 

테스트코드를 작성하는 도중 Qoute를 만들려고 하니 필수 필드들이 우수수 나왔고

그 중 Opportunity.Id를 위해 Opportunity를 생성하니 다시 또 거기서 필수 필드들이 나왔다.

 

이번에는 Pricebook2Id를 넣으라고 해서 Pricebook2를 만들려고 하니 다시 또 요구하고

데이터를 실행해보면 standard pricebook이 아니라고 하는데

직접 그 부분을 건드릴 수는 없었다.

 

결국 찾아보다가 Test.getStandardPricebookId();라는 코드를 통해

테스트에서 정규 pricebook을 가져올 수 있었고

에러코드에서 어떤 필드가 부족하다고 하는지를 보며 다시 채우고

Opportunity, Product2, Pricebook2, pricebookId, PricebookEntry, Quote를 만든 끝에

QuoteLineItem를 만들 수 있었다.

 

이 모든 작업은 @testSetup 함수 내부에서 작성했기 때문에

이 테스트 클래스 내부에서는 실존하는 데이터가 되었다.

 

한번 테스트 하는데 너무 지나치게 많은 작업 같았는데

회사분이 알려주시는걸 들어보니 팩토리라는 것을 만들어 두고

필요할 때 마다 메서드를 호출해 계정, 기회, 상품 등을 만들 수 있다고 하셨다.

 

물론 한번 진행했던 코드들을 잘 정리만 해두면 복붙으로 해결이 될 것 같긴 하지만

공용으로 쓸 수 있는 코드가 있으면 좋을 것 같다.

중간중간 clean으로 지웠지만 이정도..

데이터를 넣어뒀기 때문에

해당 코드를 바탕으로 ApexPages.currentPage().getParameters().put('id', id);를 통해 url을 설정하고

해당 url에서 QuoteDataController를 호출했고 그 상태에서 5개의 getter를 체크했다.

 

마지막으로 TableType를 테스트하려고 했는데 생각처럼 작동하지 않고 아래의 에러를 발생시켰다.

“apex test Static method cannot be referenced from a non static context”

 

계속 확인한 결과 정적 데이터는 직접 접근하라는 이야기였는데

QuoteDataController a = new QuoteDataController();

a.makePDF(id);

위의 코드처럼 생성한 뒤 사용하는 것이 아니라

아래의 코드처럼 클래스에 정적매서드를 바로 붙여서 사용하라는 이야기였다.

QuoteDataController.makePDF(id);

 

테스트코드의 Code Coverage를 100%로 만든 후

테스트코드 또한 테스트용 클래스였기 때문에 클래스용 주석을 작성해야 했다.

(하단 테스트코드)

/****************************************************************************************  
* File Name   : QuoteDataControllerTest  
* Description : getter로 데이터 받아지는지 확인 및 makePDF 파일 생성 확인
* Target      : QuoteDataController.cls 
* Author      : Yohan  
* Modification Log 
* ===============================================================  
* Ver  Date        Author	 Modification 
* =============================================================== 
* 1.0  2023.05.03  Yohan    QuoteDataController getter, makePDF 테스트
****************************************************************************************/ 
@IsTest
public class QuoteDataControllerTest {

    /**
    * @description : Quote Test를 위해 testSetup으로 데이터 insert
    * @author Yohan | 2023.05.03
    **/
    @testSetup
    static void setup() {
        //기회 제작
        Opportunity testOpportunity = new Opportunity();
        testOpportunity.Name = 'testOpportunity';
        testOpportunity.StageName = 'Draft';
        testOpportunity.CloseDate = Date.today().addDays(30);
        insert testOpportunity;
		
        //상품 제작
        Product2 productA = new Product2();
        productA.Name = 'productA';
        insert productA;
        
        Product2 productB = new Product2();
        productB.Name = 'productB';
        insert productB;
        
        //상품목록 제작
        Pricebook2 pb = new Pricebook2();
        pb.Name = 'Test Pricebook';
        pb.IsActive = true;
        insert pb;
        
		Id pricebookId = Test.getStandardPricebookId(); 
        
        //상품목록 기입 제작
        PricebookEntry spbEntryA = new PricebookEntry();
        spbEntryA.UnitPrice = 500;
        spbEntryA.Product2Id = productA.Id;
        spbEntryA.Pricebook2Id = pricebookId;
        spbEntryA.IsActive = true;
        insert spbEntryA;
        
        PricebookEntry spbEntryB = new PricebookEntry();
        spbEntryB.UnitPrice = 1000;
        spbEntryB.Product2Id = productB.Id;
        spbEntryB.Pricebook2Id = pricebookId;
        spbEntryB.IsActive = true;
        insert spbEntryB;
        
        
        //견적서 제작
        Quote testQuote = new Quote();
        testQuote.Name = 'Test Quote';
        testQuote.OpportunityId = testOpportunity.id;
        testQuote.Pricebook2Id = pricebookId;
        testQuote.Tax = 0.1;
        testQuote.ExpirationDate = Date.today().addDays(30);
        testQuote.Description = 'Test Description';
        testQuote.BillingStreet = '123 Main St';
        testQuote.BillingName = 'Test Name';
        testQuote.ShippingStreet = '123 Main St';
        testQuote.ShippingName = 'Test Name';
        testQuote.Email = 'test@example.com';
        testQuote.Phone = '555-555-5555';
        testQuote.Fax = '444-555-6666';
        insert testQuote;
        
        //견적서 상품리스트 제작
        QuoteLineItem item1 = new QuoteLineItem();
        item1.QuoteId = testQuote.Id;
        item1.PricebookEntryId = spbEntryA.Id;
        item1.Quantity = 2;
        item1.UnitPrice = 500;
        item1.Product2Id = productA.Id;
        item1.Discount = 0.1;
        item1.Description = 'Test Product 1';
        insert item1;
        
        QuoteLineItem item2 = new QuoteLineItem();
        item2.QuoteId = testQuote.Id;
        item2.PricebookEntryId = spbEntryB.Id;
        item2.Quantity = 1;
        item2.UnitPrice = 1000;
        item2.Product2Id = productB.Id;
        item2.Discount = 0.05;
        item2.Description = 'Test Product 2';
        insert item2;
    }

    /**
    * @description : getter들 테스트를 위한 함수
    * @author Yohan | 2023.05.03
    **/ 
    @isTest
    static void testGetters() {
		String id = [select id from quote].id;
        ApexPages.currentPage().getParameters().put('id', id);
        QuoteDataController controller = new QuoteDataController();
		//각 getter 테스트        
        System.assertEquals(id, controller.getQuoteId());
        System.assertEquals(controller.quote, controller.getQuote());
        System.assertEquals(controller.user, controller.getUser());
        System.assertEquals(controller.itemList, controller.getItemList());
        System.assertEquals(controller.tableData, controller.getTableData());
    }

    /**
    * @description : makePDF 테스트를 위한 테스트함수
    * @author Yohan | 2023.05.03
    **/
    @isTest
    static void testMakePDF() {
		String id = [select id from quote].id;
        Test.startTest();
        QuoteDataController.makePDF(id);               
        Test.stopTest();
        System.assertEquals(1, [select count() from QuoteDocument]);
    }
}

 

이미 주석을 작성해봤기 때문에 무난하게 테스트코드 주석을 완료했고

도중에 뭔가 실수했던 기존 주석도 수정할 수 있었다.

 

주석 수정 후 버튼이 조금 애매한 것 같아서

기존의 버튼은 PDF미리보기로 변경하고 PDF 생성 버튼을 추가해서

단촐해 보이지 않으면서도 굳이 볼 필요 없을 경우 생성한다는 당위성도 있는 버튼을 만들었다.

 

버튼에 label이 없다고 경고가 자꾸 나와서 label을 넣어주려고 했는데

apex button이라 label을 넣어주는 것은 의미없고

황당하게도 태그로 된 label 내부에 값을 넣어줘야 했다.

 

이제 클래스코드에 주석이 너무 앙상한데

날짜의 변동에 따라 차이가 있을 수 있도록 작성해주는 과정이 필요할 것 같고

해당 작업을 위해 현재 작성중인 과제 일지를 다시 한번 쭉 읽어보며 수정을 진행하다가

퇴근 시간이 되서 LWC 주석부분까지만 수정한채 마무리했다.

 

 

 

 

 

(1).백준 12790번 Mini Fantasy War는

const input = `3
100 100 100 100 0 0 0 0
10 20 30 40 40 30 20 10
100 100 100 100 -200 0 400 400`.split('\n')

const result = []

for(let i = 1 ; i < input.length ; i++){
    const[a,b,c,d,a2,b2,c2,d2] = input[i].split(' ').map(Number)
    let sum = 0
    sum += Math.max(1, (a+a2))*1
    sum += Math.max(1, (b+b2))*5
    sum += Math.max(0, (c+c2))*2
    sum += (d+d2)*2
    result.push(sum)
}
console.log(result.join('\n'))

'회고' 카테고리의 다른 글

[수습일지] - 40(어린이날)  (0) 2023.05.05
[수습일지] - 39  (0) 2023.05.04
[수습일지] - 37  (0) 2023.05.02
[수습일지] - 36(근로자의 날)  (0) 2023.05.01
[수습일지] - 35(주말)  (0) 2023.04.30

+ Recent posts