Umgang mit Blockverzögerungen in Unit-Tests

Betrachten Sie den folgenden in JavaScript geschriebenen Truffle Unit Test:

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);                                                                                   



    });                                                                                             
});

Wenn ich diesen Test auf meiner GanacheUI-Instanz ohne Blockverzögerungen ausführe, erhalte ich die folgenden Ergebnisse:

$ 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

Wenn ich jedoch in GanacheUI eine Blockverzögerung von 15 Sekunden hinzufüge (was ungefähr der gleichen Blockverzögerung wie im Hauptnetz entspricht), erhalte ich Folgendes:

$ 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

Das hat verheerende Auswirkungen auf meine Unit-Tests: Rund 70 % davon scheitern mit ganz unterschiedlichen Fehlern.

Ich habe ähnliche Ergebnisse mit dem Repository von AragonOS mit GanacheUI erhalten: Ohne Blockverzögerungen bestehen alle Tests, aber mit einer Blockverzögerung von 15 Sekunden schlagen viele fehl. (Sie haben die Möglichkeit, Ropsten, Kovan und Rinkeby mit Infura zu testen, aber das habe ich nicht versucht).

Was sind also die besten Praktiken? Sollte ich Blockverzögerungen ganz ignorieren? Wie soll ich in diesem Fall meine Verträge in den Testnetzen testen? Oder sollte ich meine Tests so gestalten, dass sie Blockverzögerungen richtig handhaben? Wenn das so ist, wie? Und schließlich: Gibt es Auswirkungen auf die Sicherheit, wenn Blockverzögerungen in Komponententests ignoriert werden?

Antworten (1)

Es ist besser, wenn Sie Ihre Tests so gestalten, dass sie nicht von der Verzögerung zwischen den Blöcken abhängen. In einem realen Netzwerk werden Blöcke im Durchschnitt nur alle 15 Sekunden generiert und können längere oder kürzere Intervalle dauern. Auch in Zukunft kann der Netzdurchschnitt gesenkt werden.

In Ihrem Komponententest besteht das Problem darin, dass Sie den Status Ihres Vertrags ändern. Sie können nicht sicher sein, wann Sie die Abfrage beenden müssen. In einem privaten Testnetzwerk sollten 30 Sekunden warten, in einem wenig genutzten Netzwerk wie rinkeby reichen vielleicht ein paar Minuten, aber in einem ausgelasteten Netzwerk wie dem Mainnet reichen 10 Minuten möglicherweise nicht aus.

Ein besserer Ansatz ist hier, ein Ereignis mit Ihrer Transaktion zu generieren und Ihren Test darauf warten zu lassen, dass dieses Ereignis ausgelöst wird. Sie müssen sicherstellen, dass der verwendete Gaspreis die Verarbeitung der Transaktionen in einem öffentlichen Netz mit geringer Verzögerung ermöglicht.