6

It seems that truffle test automatically invokes truffle deploy (aka truffle migrate).

As far as I'm concerned, these two functionalities are completely unrelated.

So I cannot quite figure out why Truffle works this way to begin with.

The docs do not seem to mention anything on this subject.

I would like to use truffle test for one thing and truffle deploy for another thing.

Is there any way to "tell" truffle test to avoid running truffle deploy?

Thank you!!!

2

Before you can run any test, one has to define the starting point, the starting conditions in the smart contract. - Think about the values of the variable in the smart contracts. These conditions are defined by the deployment process. Hence, usually one would first run the deployment before testing. Also, this allows resetting the blockchain easily after each separate test.

If you do not want to do this, you might wanna try truffle scripts. They allow you to run any script or test.

  • Thank you. No, I would like to use truffle test because it provides a good report. I would like to create/deploy contracts myself - different contracts on each test. And most certainly not the same ones for every test. In some of my tests I use mockup contracts, with the purpose of testing a single contract in an isolated manner (aka unitest). In the migration script passed to truffle deploy, I would like to do "the real thing", since here my intention is not to test the contracts but to actually deploy them. – goodvibration May 28 '18 at 11:26
  • Then you might wanna use flags for the deployment: truffleframework.com/docs/advanced/configuration If no flag is passed, you simply do not execute any deployment code. Then truffle test runs through without deploying. If you hand over --network "testnetName" you could execute the deployment in the migration. – josojo May 28 '18 at 15:25
  • That's exactly how I ended up solving it, BTW (execute only if network == "production"). Thanks. – goodvibration May 28 '18 at 17:35
  • 1
    Though I wouldn't call them "flags", there are indeed 3 parameters passed to the script - deployer, network and accounts. – goodvibration May 28 '18 at 17:37
2

I ran into this issue as well, and it is indeed the intended behavior of truffle test: cleanroom behavior. Each run of truffle test redeploys the contracts. If it didn't, then saved state from a prior run could affect the results of a subsequent run, making your test suite non-deterministic.

But I wanted to preserve state between runs of truffle test. The suggested way to do this is documented as:

deployer.deploy(Contract, {overwrite: false})

Unfortunately, the above seems to fail in truffle 5.0.1 due to a parsing bug. So a workaround to force correct parsing is this:

deployer.deploy(Contract, {gas: 6720000, overwrite: false})

https://truffleframework.com/docs/truffle/testing/testing-your-contracts#clean-room-environment

Clean-room environment

Truffle provides a clean room environment when running your test files. When running your tests against Ganache or Truffle Develop, Truffle will use advanced snapshotting features to ensure your test files don't share state with each other. When running against other Ethereum clients like go-ethereum, Truffle will re-deploy all of your migrations at the beginning of every test file to ensure you have a fresh set of contracts to test against.

  • 1
    Nice answer, but it'd be even better if you linked to that parsing bug to see what's the status/workarounds/etc. – hmijail Jul 2 at 9:33
2

It is really embarrassing, how narrow minded the truffle authors think. My tests run their own deployment that is used in the tests. In my case, the truffle migration includes the steps that data is copied from the old instance to the new instance of the main contract, then the old contract is destroyed. Unfortunately, here the snapshot does not help, the old instance is not restored and a defect instance remains in the contract's json file. So I have to prevent the migration scripts from running. So there are good reasons, why migration should be optional and configurable in truffle test!

I solved it in the following way:

  • run a second canache-cli with a separete network named test
  • if the truffle migrate script is in network test, do nothing
  • run truffle test with option --network test

In detail:

Add on top of migrations/2_contract the line:

module.exports = async function(deployer, network, accounts) {
  if (network == "test") return; // test maintains own contracts
  …
}

Add new network test to truffle-config.js:

…
networks: {
  …
  development: {
    host: "127.0.0.1",
    port: 8545,
    network_id: "*"
  },
  test: {
    host: "127.0.0.1",
    port: 8546,
    network_id: "*"
  }
}
…

Run a second canache-cli (besides the one running network development:

In one console, I run ganache for development, for my GUI tests:

ganache-cli -d --db ${HOME}/tmp/ganache/development -i 123456 -p 8545

In another console, I run a separate ganache for test:

ganache-cli -d --db ${HOME}/tmp/ganache/test -i 654321 -p 8546

That's it! Now I can run:

truffle migrate --reset

And

truffle test --network test

Without interferences.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.