Skip to content

Instantly share code, notes, and snippets.

@BadUncleX
Last active June 14, 2020 15:16
Show Gist options
  • Save BadUncleX/ed17be940b1dceda0f3b91904dd98529 to your computer and use it in GitHub Desktop.
Save BadUncleX/ed17be940b1dceda0f3b91904dd98529 to your computer and use it in GitHub Desktop.
how to write #unittests in #substrate

detail commit from here:

Github Commit

git command from:

git diff-tree -p 16a7aca8f3b5e4269c9ea4ca683b483a59dadee1

result

16a7aca8f3b5e4269c9ea4ca683b483a59dadee1
diff --git a/lesson3/substrate-node-template/pallets/poe/src/mock.rs b/lesson3/substrate-node-template/pallets/poe/src/mock.rs
index 951e468..f1ca265 100644
--- a/lesson3/substrate-node-template/pallets/poe/src/mock.rs
+++ b/lesson3/substrate-node-template/pallets/poe/src/mock.rs
@@ -31,6 +31,7 @@ impl system::Trait for Test {
 	type BlockNumber = u64;
 	type Hash = H256;
 	type Hashing = BlakeTwo256;
+	// 注意这两个声明 AccountId 和 Lookup
 	type AccountId = u64;
 	type Lookup = IdentityLookup<Self::AccountId>;
 	type Header = Header;
@@ -49,12 +50,13 @@ impl system::Trait for Test {
 	type OnNewAccount = ();
 	type OnKilledAccount = ();
 }
-
+// 测试需要用到的常量声明
 parameter_types! {
 	pub const MaxClaimLength: u32 = 6;
 }
 impl Trait for Test {
 	type Event = ();
+	// 测试需要用到的常量声明
 	type MaxClaimLength = MaxClaimLength;
 }
 pub type PoeModule = Module<Test>;
@@ -62,6 +64,7 @@ pub type PoeModule = Module<Test>;
 
 // This function basically just builds a genesis storage key/value store according to
 // our desired mockup.
+// test 里用到的基本函数库, 公用
 pub fn new_test_ext() -> sp_io::TestExternalities {
 	system::GenesisConfig::default().build_storage::<Test>().unwrap().into()
 }
diff --git a/lesson3/substrate-node-template/pallets/poe/src/tests.rs b/lesson3/substrate-node-template/pallets/poe/src/tests.rs
index 83da5e7..bff9831 100644
--- a/lesson3/substrate-node-template/pallets/poe/src/tests.rs
+++ b/lesson3/substrate-node-template/pallets/poe/src/tests.rs
@@ -8,9 +8,13 @@ use super::*;
 #[test]
 fn create_claim_works() {
 
+    // 测试中使用mock中声明的new_test_ext
     new_test_ext().execute_with(|| {
         let claim = vec![0, 1];
+        // 执行成功的操作, 使用 assert_ok!
         assert_ok!(PoeModule::create_claim(Origin::signed(1), claim.clone()));
+
+        // 逻辑相等操作, 使用 assert_eq!
         assert_eq!(Proofs::<Test>::get(&claim), (1, system::Module::<Test>::block_number()));
     })
 }
@@ -23,6 +27,7 @@ fn create_claim_failed_when_claim_already_exists() {
         let claim = vec![0, 1];
         let _ = PoeModule::create_claim(Origin::signed(1), claim.clone());
 
+        // 预期返回一个指定的错误, 使用 assert_noop!
         assert_noop!(
             PoeModule::create_claim(Origin::signed(1), claim.clone()),
             Error::<Test>::ProofAlreadyExist
#![cfg_attr(not(feature = "std"), no_std)]
/// A FRAME pallet proof of existence with necessary imports
use frame_support::{
decl_module, decl_storage, decl_event, decl_error, dispatch, ensure,
traits::{Get},
};
use frame_system::{self as system, ensure_signed};
use sp_std::prelude::*;
use sp_runtime::traits::StaticLookup;
#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;
/// The pallet's configuration trait.
pub trait Trait: system::Trait {
// Add other types and constants required to configure this pallet.
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
// 附加题答案
type MaxClaimLength: Get<u32>;
}
// This pallet's storage items.
decl_storage! {
// It is important to update your storage name so that your pallet's
// storage items are isolated from other pallets.
// ---------------------------------vvvvvvvvvvvvvv
trait Store for Module<T: Trait> as TemplateModule {
Proofs get(fn proofs): map hasher(blake2_128_concat) Vec<u8> => (T::AccountId, T::BlockNumber);
}
}
// The pallet's events
decl_event!(
pub enum Event<T> where AccountId = <T as system::Trait>::AccountId {
ClaimCreated(AccountId, Vec<u8>),
ClaimRevoked(AccountId, Vec<u8>),
ClaimTransfered(AccountId, Vec<u8>, AccountId),
}
);
// The pallet's errors
decl_error! {
pub enum Error for Module<T: Trait> {
ProofAlreadyExist,
ClaimNotExist,
NotClaimOwner,
ProofTooLong,
}
}
// The pallet's dispatchable functions.
decl_module! {
/// The module declaration.
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
// Initializing errors
// this includes information about your errors in the node's metadata.
// it is needed only if you are using errors in your pallet
type Error = Error<T>;
// Initializing events
// this is needed only if you are using events in your pallet
fn deposit_event() = default;
#[weight = 0]
pub fn create_claim(origin, claim: Vec<u8>) -> dispatch::DispatchResult {
let sender = ensure_signed(origin)?;
ensure!(!Proofs::<T>::contains_key(&claim), Error::<T>::ProofAlreadyExist);
// 附加题答案
ensure!(T::MaxClaimLength::get() >= claim.len() as u32, Error::<T>::ProofTooLong);
Proofs::<T>::insert(&claim, (sender.clone(), system::Module::<T>::block_number()));
Self::deposit_event(RawEvent::ClaimCreated(sender, claim));
Ok(())
}
#[weight = 0]
pub fn revoke_claim(origin, claim: Vec<u8>) -> dispatch::DispatchResult {
let sender = ensure_signed(origin)?;
ensure!(Proofs::<T>::contains_key(&claim), Error::<T>::ClaimNotExist);
let (owner, _block_number) = Proofs::<T>::get(&claim);
ensure!(owner == sender, Error::<T>::NotClaimOwner);
Proofs::<T>::remove(&claim);
Self::deposit_event(RawEvent::ClaimRevoked(sender, claim));
Ok(())
}
// 第二题答案
#[weight = 0]
pub fn transfer_claim(origin, claim: Vec<u8>, dest: <T::Lookup as StaticLookup>::Source) -> dispatch::DispatchResult {
let sender = ensure_signed(origin)?;
ensure!(Proofs::<T>::contains_key(&claim), Error::<T>::ClaimNotExist);
let (owner, _block_number) = Proofs::<T>::get(&claim);
ensure!(owner == sender, Error::<T>::NotClaimOwner);
let dest = T::Lookup::lookup(dest)?;
Proofs::<T>::insert(&claim, (dest.clone(), system::Module::<T>::block_number()));
Self::deposit_event(RawEvent::ClaimTransfered(sender, claim, dest.clone()));
Ok(())
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment