요즘 자꾸 발생하는 문제인데
인증이 자꾸 실패하면서 작업을 진행시키는 일이 발생했다.
이전에는 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 함수 내부에서 작성했기 때문에
이 테스트 클래스 내부에서는 실존하는 데이터가 되었다.
한번 테스트 하는데 너무 지나치게 많은 작업 같았는데
회사분이 알려주시는걸 들어보니 팩토리라는 것을 만들어 두고
필요할 때 마다 메서드를 호출해 계정, 기회, 상품 등을 만들 수 있다고 하셨다.
물론 한번 진행했던 코드들을 잘 정리만 해두면 복붙으로 해결이 될 것 같긴 하지만
공용으로 쓸 수 있는 코드가 있으면 좋을 것 같다.

데이터를 넣어뒀기 때문에
해당 코드를 바탕으로 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 |
