Skip to content

Implement unit tests for learn-token contract (tests/unit/token_tests.rs) #1

Description

@DeFiVC

Description

The file tests/unit/token_tests.rs contains 8 test function skeletons for the learn-token contract. Every test has the correct #[test] / #[should_panic] annotations and Soroban Env setup, but all contract invocations and assertions are commented out. As a result, these tests compile and "pass" without exercising any contract logic.

The goal is to uncomment and wire up these tests so they call the real LearnToken contract and assert real behavior.

How to set up each test

Every test needs to:

  1. Create a Soroban Env with Env::default()
  2. Generate an admin address with Address::generate(&env)
  3. Register the contract: let contract_id = env.register(LearnToken, ());
  4. Create a client: let client = LearnTokenClient::new(&env, &contract_id);
  5. Initialize the token: client.initialize(&admin, &Symbol::new(&env, "CLearn"), &Symbol::new(&env, "CLRN"), &7);
  6. Call env.mock_all_auths(); to bypass auth checks in tests

The inline tests at the bottom of contracts/learn-token/src/lib.rs (lines 239-335) show working examples of this pattern.

Tests to uncomment and complete

test_token_metadata_after_init

What it verifies: After initialization, name(), symbol(), decimals(), and total_supply() return the correct values.

let (admin, contract_id) = setup_token(&env);
let client = LearnTokenClient::new(&env, &contract_id);
assert_eq!(client.name(), Symbol::new(&env, "CLearn"));
assert_eq!(client.symbol(), Symbol::new(&env, "CLRN"));
assert_eq!(client.decimals(), 7);
assert_eq!(client.total_supply(), 0);
assert_eq!(client.admin(), admin);

test_mint_increases_balance_and_supply

What it verifies: mint(&recipient, &1000) increases balance(&recipient) to 1000 and total_supply() to 1000.

client.mint(&recipient, &1000);
assert_eq!(client.balance(&recipient), 1000);
assert_eq!(client.total_supply(), 1000);

test_transfer_moves_tokens

What it verifies: After minting 500 to alice, transfer(&alice, &bob, &200) leaves alice with 300 and bob with 200.

client.mint(&alice, &500);
client.transfer(&alice, &bob, &200);
assert_eq!(client.balance(&alice), 300);
assert_eq!(client.balance(&bob), 200);

test_transfer_insufficient_balance

What it verifies: #[should_panic(expected = "insufficient balance")] — transferring more than balance panics.

client.mint(&alice, &100);
client.transfer(&alice, &bob, &200);  // panics

test_claim_reward_proportional_minting

What it verifies: claim_reward(&learner, &quiz_id, &80) returns 80 * 100 = 8000 (BASE_REWARD_PER_POINT = 100 from packages/shared/src/constants.rs:13). Balance and total_supply should also be 8000.

let quiz_id = Symbol::new(&env, "quiz_1");
let reward = client.claim_reward(&learner, &quiz_id, &80);
assert_eq!(reward, 8000);
assert_eq!(client.balance(&learner), 8000);
assert_eq!(client.total_supply(), 8000);

test_claim_reward_double_claim

What it verifies: #[should_panic(expected = "reward already claimed")] — calling claim_reward twice with the same quiz_id panics.

let quiz_id = Symbol::new(&env, "quiz_1");
client.claim_reward(&learner, &quiz_id, &80);
client.claim_reward(&learner, &quiz_id, &80);  // panics

test_claim_reward_rejects_high_score

What it verifies: #[should_panic(expected = "score exceeds maximum")] — score > 100 (MAX_QUIZ_SCORE) panics.

let quiz_id = Symbol::new(&env, "quiz_1");
client.claim_reward(&learner, &quiz_id, &101);  // panics

test_transfer_from_with_allowance

What it verifies: approve(&owner, &spender, &500, &999999) sets allowance, then transfer_from(&spender, &owner, &recipient, &300) moves 300 and decreases allowance to 200.

client.mint(&owner, &1000);
client.approve(&owner, &spender, &500, &999999);
client.transfer_from(&spender, &owner, &recipient, &300);
assert_eq!(client.balance(&owner), 700);
assert_eq!(client.balance(&recipient), 300);
assert_eq!(client.allowance(&owner, &spender), 200);

Imports needed

use learn_token::{LearnToken, LearnTokenClient};
use soroban_sdk::{symbol_short, testutils::Address as _, Address, Env, Symbol};

How to run

cd chainlearn-contracts
cargo test --package learn-token --test token_tests

References

  • Contract source: contracts/learn-token/src/lib.rs (335 lines)
  • Storage layer: contracts/learn-token/src/storage.rs (120 lines)
  • Constants: packages/shared/src/constants.rsBASE_REWARD_PER_POINT = 100, MAX_QUIZ_SCORE = 100, TOKEN_DECIMALS = 7
  • Working inline test examples: contracts/learn-token/src/lib.rs:239-335
  • Soroban testing docs: https://soroban.stellar.org/docs

Metadata

Metadata

Assignees

No one assigned

    Labels

    good first issueGood for newcomersrustRust languagetestsTest additions or improvements

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions