본문으로 건너뛰기

Integration Tests

통합 테스트를 사용하면 NEAR testnet 또는 로컬 sandbox에 컨트랙트를 배포하고, 컨트랙트와 상호 작용할 테스트 사용자를 만들 수 있습니다. 그러한 방식으로, 현실적인 환경에서 컨트랙트를 철저하게 테스트할 수 있습니다.

또한 로컬 sandbox을 사용하면 네트워크를 완전히 제어할 수 있습니다.

  1. 테스트 Accounts를 생성하고 그들의 StateBalance를 처리합니다.
  2. 콜백에서 에러를 시뮬레이션합니다.
  3. 시간 흐름을 제어하고, 미래로 빠르게 이동합니다(Rust에서는 준비된 기능이고, TS에서는 출시 예정입니다).
NEAR Workspaces

In NEAR, integration tests are implemented using a framework called Workspaces. 작업 공간은 🦀 Rust🌐 Typescript의 두 가지 유형으로 제공됩니다.

All of our examples come with integration testing.


스니펫 I: Hello NEAR 테스트

Lets take a look at the test of our Quickstart Project 👋 Hello NEAR, where we deploy the contract on an account and test it correctly retrieves and sets the greeting.

contract-ts/sandbox-ts/main.ava.ts
loading...

Snippet II: Testing Donations

In most cases we will want to test complex methods involving multiple users and money transfers. A perfect example for this is our Donation Example, which enables users to donate money to a beneficiary. Lets see its integration tests

contract-ts/sandbox-ts/src/main.ava.ts
loading...

Sandbox Testing

NEAR Workspaces allows you to write tests once, and run them either on testnet or a local Sandbox. 기본적으로, 작업 공간은 샌드박스를 시작하고, 로컬 환경에서 테스트를 실행합니다. 이 프레임워크의 기능에 대해 자세히 알아보고, 해당 프레임워크가 어떻게 도움이 되는지 살펴보겠습니다.

Spooning Contracts

블록체인을 스푸닝하는 것은 한 네트워크에서 다른 네트워크로 데이터를 복사하는 것입니다. NEAR 작업 공간을 사용하면, Mainnet 또는 Testnet 컨트랙트에서 로컬 샌드박스 환경으로 데이터를 쉽게 복사할 수 있습니다.

const refFinance = await root.importContract({
mainnetContract: 'v2.ref-finance.near',
blockId: 50_000_000,
withData: true,
});

This would copy the Wasm bytes and contract state from v2.ref-finance.near to your local blockchain as it existed at block 50_000_000. 최상위 계정이 로컬에 존재하지 않더라도 컨트랙트 이름을 동일하게 유지하기 위해, 여기서는 샌드박스의 특수한 패치 상태 기능을 사용합니다 (이는 샌드박스 테스트 모드에서만 작동함을 의미합니다). 이렇게 하면 가까운 작업 공간에서 생성된 다른 모든 계정과 상호 작용하는 것과 동일하게, 결정론적 방식으로 컨트랙트와 상호 작용할 수 있습니다.

노트

withData will only work out-of-the-box if the contract's data is 50kB or less. 이는 RPC 서버의 기본 구성 때문입니다.

컨트랙트 스푸닝에 대한 TypeScript 예제를 참조하세요.

실시간 상태 패치

샌드박스 모드에서는 컨트랙트 상태, 컨트랙트 코드, 계정 또는 액세스 키를 patchState로 추가하거나 수정할 수 있습니다.

DeployContract, CreateAccountAddKey 작업(Action)을 통해 일반 트랜잭션을 사용하여 컨트랙트 코드, 계정 및 액세스 키를 변경할 수 있습니다. 그러나 이것은 자신의 계정 또는 하위 계정을 변경하는 것만으로 제한됩니다. patchState를 통해 모든 계정에서 이러한 작업을 수행할 수 있습니다.

트랜잭션은 컨트랙트가 프로그램된 방식으로 상태를 변경하는 컨트랙트 호출만 포함할 수 있기 때문에, 트랜잭션을 통해 컨트랙트 상태에 대해 임의로 변경하는 작업을 수행할 수 없음을 명심하세요. 예를 들어 NFT 컨트랙트를 사용하면 소유권을 가진 NFT에 대해 작업을 수행할 수는 있지만, 다른 계정이 소유한 NFT에 대해 작업하는 것은 불가능합니다. 이것은 NFT 컨트랙트의 예상된 작동 방식입니다. 그러나 테스트를 위해 다른 사람의 NFT를 변경하고 싶을 수 있습니다. 이를 "컨트랙트 상태의 임의 변경"이라고 하며, patchState를 통해 수행할 수 있습니다.

    const {contract, ali} = t.context.accounts;
// Contract must have some state for viewState & patchState to work
await ali.call(contract, 'set_status', {message: 'hello'});
// Get state
const state = await contract.viewState();
// Get raw value
const statusMessage = state.get('STATE', {schema, type: StatusMessage});
// Update contract state
statusMessage.records.push(
new BorshRecord({k: 'alice.near', v: 'hello world'}),
);
// Serialize and patch state back to runtime
await contract.patchState(
'STATE',
borsh.serialize(schema, statusMessage),
);
// Check again that the update worked
const result = await contract.view('get_status', {
account_id: 'alice.near',
});
t.is(result, 'hello world');

이를 수행하는 방법에 대한 전체 예제를 보고 싶다면, 상태 패치 테스트를 참조하세요.

patchState 대신, 노드를 중지하고 제네시스에서 상태를 덤프한 다음, 제네시스를 편집하고 노드를 다시 시작할 수 있습니다. 이 접근 방식은 수행하기가 더 복잡하며, 노드를 다시 시작하지 않고서는 수행할 수도 없습니다.

시간 이동

workspaces offers support for forwarding the state of the blockchain to the future. 즉, 시간에 민감한 데이터가 필요한 컨트랙트는 샌드박스의 블록이 생성될 때까지 앉아서 기다릴 필요가 없습니다. We can simply just call worker.fast_forward to get us further in time:

__tests__/08.fast-forward.ava.ts
loading...

테스트넷 사용

NEAR 작업 공간은 테스트를 작성한 뒤 로컬 샌드박스 노드(기본 동작) 또는 NEAR TestNet에 대해 실행할 수 있도록 설정됩니다. 이것이 도움이 될 수 있는 이유는 다음과 같습니다.

  • 컨트랙트가 예상대로 작동한다는 높은 신뢰성 제공
  • 배포된 테스트넷 컨트랙트에 대한 테스트 가능
  • 샌드박스 모드에서 뭔가 꺼지는 것 같으면 테스트넷과 비교 가능

테스트넷 모드에서 Workspaces를 사용하려면 testnet 계정이 있어야 합니다. You can create one here.

다음과 같은 세 가지 단계를 통해 테스트넷 모드로 전환할 수 있습니다.

  1. testnet에 작업자 설정 네트워크를 만들고 마스터 계정을 전달할 때
const worker = await Worker.init({
network: 'testnet',
testnetMasterAccountId: '<yourAccountName>',
})
  1. 테스트를 실행할 때, NEAR_WORKSPACES_NETWORKTESTNET_MASTER_ACCOUNT_ID 환경 변수를 설정
NEAR_WORKSPACES_NETWORK=testnet TESTNET_MASTER_ACCOUNT_ID=<your master account Id> node test.js

이 환경 변수를 설정하고, {network: 'testnet', testnetMasterAccountId: <masterAccountId>}Worker.init에 전달하면 구성 객체가 우선합니다.

  1. AVA를 통해 near-workspaces를 사용하고 있다면 커스텀 구성 파일을 사용할 수 있습니다. 다른 테스터들도 유사한 구성 파일을 허용합니다.

다음과 같은 형태로 ava.testnet.config.cjs 파일을 package.json과 동일한 디렉토리에 만듭니다.

module.exports = {
...require('near-workspaces/ava.testnet.config.cjs'),
...require('./ava.config.cjs'),
};
module.exports.environmentVariables = {
TESTNET_MASTER_ACCOUNT_ID: '<masterAccountId>',
};

near-workspaces/ava.testnet.config.cjs 가져오기(import)는 NEAR_WORKSPACES_NETWORK 환경 변수를 설정합니다. 이 접근 방식의 이점은 샌드박스 모드에서만 실행되어야 하는 파일을 쉽게 무시할 수 있다는 것입니다.

이제 package.jsonscripts 섹션에 test:testnet 스크립트를 추가하고 싶다면, 다음과 같이 할 수 있습니다.

"scripts": {
"test": "ava",
+ "test:testnet": "ava --config ./ava.testnet.config.cjs"
}

추가 미디어 자료

작업 공간과 AVA를 사용한 테스트 기반 설계

아래 비디오는 간단한 컨트랙트를 위해 TDD에 작업 공간 및 AVA를 적용하는 방법에 대해 안내합니다.

Was this page helpful?