Skip to content

Commit

Permalink
impl: test sub cmd with support for --manifest-path (use-ink#280) (us…
Browse files Browse the repository at this point in the history
  • Loading branch information
chiefbiiko authored Jul 3, 2021
1 parent 50d2792 commit 78d4d4e
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ test-new-project-template:

- cargo run --all-features -- contract build --manifest-path new_project/Cargo.toml
- cargo run --all-features -- contract check --manifest-path new_project/Cargo.toml
- cargo run --all-features -- contract test --manifest-path new_project/Cargo.toml
- cd new_project

- cargo check --verbose
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ toolchain of a directory by executing `rustup override set nightly` in it.
Checks that the code builds as WebAssembly. This command does not output any `<name>.contract`
artifact to the `target/` directory.

##### `cargo contract test`

Runs test suites defined for a smart contract off-chain.

## License

Expand Down
6 changes: 5 additions & 1 deletion src/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ mod deploy;
mod instantiate;
pub mod metadata;
pub mod new;
pub mod test;

pub(crate) use self::build::{BuildCommand, CheckCommand};
pub(crate) use self::{
build::{BuildCommand, CheckCommand},
test::TestCommand,
};
#[cfg(feature = "extrinsics")]
pub(crate) use self::{deploy::execute_deploy, instantiate::execute_instantiate};
94 changes: 94 additions & 0 deletions src/cmd/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright 2018-2021 Parity Technologies (UK) Ltd.
// This file is part of cargo-contract.
//
// cargo-contract is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// cargo-contract is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with cargo-contract. If not, see <http://www.gnu.org/licenses/>.

use crate::{maybe_println, util, workspace::ManifestPath, Verbosity, VerbosityFlags};
use anyhow::Result;
use colored::Colorize;
use std::{convert::TryFrom, path::PathBuf};
use structopt::StructOpt;

/// Executes smart-contract tests off-chain by delegating to `cargo test`.
#[derive(Debug, StructOpt)]
#[structopt(name = "test")]
pub struct TestCommand {
/// Path to the `Cargo.toml` of the contract to test.
#[structopt(long, parse(from_os_str))]
manifest_path: Option<PathBuf>,
#[structopt(flatten)]
verbosity: VerbosityFlags,
}

impl TestCommand {
pub fn exec(&self) -> Result<TestResult> {
let manifest_path = ManifestPath::try_from(self.manifest_path.as_ref())?;
let verbosity = TryFrom::<&VerbosityFlags>::try_from(&self.verbosity)?;

execute(&manifest_path, verbosity)
}
}

/// Result of the test runs.
pub struct TestResult {
/// The `cargo +nightly test` child process standard output stream buffer.
pub stdout: Vec<u8>,
/// The verbosity flags.
pub verbosity: Verbosity,
}

impl TestResult {
pub fn display(&self) -> Result<String> {
Ok(String::from_utf8(self.stdout.clone())?)
}
}

/// Executes `cargo +nightly test`.
pub(crate) fn execute(manifest_path: &ManifestPath, verbosity: Verbosity) -> Result<TestResult> {
util::assert_channel()?;

maybe_println!(
verbosity,
" {} {}",
format!("[{}/{}]", 1, 1).bold(),
"Running tests".bright_green().bold()
);

let stdout = util::invoke_cargo("test", &[""], manifest_path.directory(), verbosity)?;

Ok(TestResult { stdout, verbosity })
}

#[cfg(feature = "test-ci-only")]
#[cfg(test)]
mod tests_ci_only {
use crate::{util::tests::with_new_contract_project, Verbosity};
use regex::Regex;

#[test]
fn passing_tests_yield_stdout() {
with_new_contract_project(|manifest_path| {
let ok_output_pattern =
Regex::new(r"test result: ok. \d+ passed; 0 failed; \d+ ignored")
.expect("regex pattern compilation failed");

let res =
super::execute(&manifest_path, Verbosity::Default).expect("test execution failed");

assert!(ok_output_pattern.is_match(&String::from_utf8_lossy(&res.stdout)));

Ok(())
})
}
}
13 changes: 10 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ mod workspace;

use self::workspace::ManifestPath;

use crate::cmd::{metadata::MetadataResult, BuildCommand, CheckCommand};
use crate::cmd::{metadata::MetadataResult, BuildCommand, CheckCommand, TestCommand};

#[cfg(feature = "extrinsics")]
use sp_core::{crypto::Pair, sr25519, H256};
Expand Down Expand Up @@ -383,7 +383,7 @@ enum Command {
Check(CheckCommand),
/// Test the smart contract off-chain
#[structopt(name = "test")]
Test {},
Test(TestCommand),
/// Upload the smart contract code to the chain
#[cfg(feature = "extrinsics")]
#[structopt(name = "deploy")]
Expand Down Expand Up @@ -472,7 +472,14 @@ fn exec(cmd: Command) -> Result<Option<String>> {
Ok(None)
}
}
Command::Test {} => Err(anyhow::anyhow!("Command unimplemented")),
Command::Test(test) => {
let res = test.exec()?;
if res.verbosity.is_verbose() {
Ok(Some(res.display()?))
} else {
Ok(None)
}
}
#[cfg(feature = "extrinsics")]
Command::Deploy {
extrinsic_opts,
Expand Down

0 comments on commit 78d4d4e

Please sign in to comment.