Работа с блочными задержками в модульных тестах

Рассмотрим следующий модульный тест Truffle, написанный на JavaScript:

const Lease = artifacts.require("./Lease.sol");                                                     
contract("Lease", async (accounts) => {                                                             
    it("Rinkeby delay problem", async () => {                                                       
    let instance = await Lease.deployed();                                                      



    // let's check the initial state                                                            
    let state0 = await instance.tenantState();                                                  
    console.log("initial state: " + state0);                                                    



    // let's change the state                                                                   
    let tx = {from:accounts[2], to:instance.address, value:2000};                               
    web3.eth.sendTransaction(tx);                                                               
    await instance.updateTenantState();                                                         



    // let's check if the state changed                                                         
    let state1 = await instance.tenantState();                                                  
    console.log("resulting state: " + state1);                                                  



    // let's wait for one second and check the state again                                      
    setTimeout(async () => {                                                                    
        await instance.updateTenantState();                                                     
        let state2 = await instance.tenantState();                                              
        console.log("resulting state after 1 second: " + state2);                               
    }, 1000);                                                                                   



    });                                                                                             
});

Когда я запускаю этот тест на моем экземпляре GanacheUI с нулевыми задержками блоков, я получаю следующие результаты:

$ truffle test test/delay.test.js --network dev
Using network 'dev'.

Compiling ./contracts/Lease.sol...
Compiling ./contracts/LeaseMock.sol...
Compiling ./contracts/Logic.sol...


  Contract: Lease
initial state: 1
resulting state: 0Delay problem (196ms)


  1 passing (226ms)

resulting state after 1 second: 0

Однако, когда я добавляю 15-секундную задержку блока в GanacheUI (примерно такая же задержка блока, что и в основной сети), я получаю следующее:

$ truffle test test/delay.test.js --network dev
Using network 'dev'.

Compiling ./contracts/Lease.sol...
Compiling ./contracts/LeaseMock.sol...
Compiling ./contracts/Logic.sol...


  Contract: Lease
initial state: 1
resulting state: 1Delay problem (30212ms)


  1 passing (30s)

resulting state after 1 second: 0

Это катастрофически сказывается на моих модульных тестах: около 70% из них терпят неудачу с самыми разными ошибками.

Я получил похожие результаты с репозиторием AragonOS с использованием GanacheUI: без задержки блоков все тесты проходят успешно, но с задержкой блока 15 секунд многие терпят неудачу. (У них есть возможность протестировать на Ropsten, Kovan и Rinkeby с помощью Infura, но я этого не пробовал).

Итак, каковы лучшие практики? Должен ли я вообще игнорировать задержки блоков? В таком случае, как я должен тестировать свои контракты в тестовых сетях? Или мне следует спроектировать свои тесты так, чтобы они правильно обрабатывали задержки блоков? Если да, то как? И наконец: есть ли последствия для безопасности игнорирования блочных задержек в модульных тестах?

Ответы (1)

Лучше, если вы спроектируете свои тесты так, чтобы они не зависели от задержки между блоками. В реальной сети блоки генерируются в среднем каждые 15 секунд, и они могут занимать более длинные или более короткие интервалы. Также в будущем среднее значение сети может быть снижено.

В вашем модульном тесте проблема заключается в том, что вы запрашиваете изменение состояния вашего контракта. Вы не можете быть уверены, когда остановить опрос, в частной тестовой сети должно быть достаточно ожидания 30 секунд, в малоиспользуемой сети, такой как rinkeby, возможно, будет достаточно пары минут, но в загруженной сети, такой как основная сеть, 10 минут может быть недостаточно.

Лучший подход здесь — сгенерировать событие с вашей транзакцией и заставить ваш тест ждать запуска этого события. Вы должны убедиться, что используемая цена газа позволит обрабатывать транзакции с небольшой задержкой в ​​общедоступной сети.