Precondition ---------- assert amount > 0, "PRE violation: amount must be > 0" assert self.status == "active", "PRE violation: status must be 'active'" assert amount <= self.balance, "PRE violation: amount must not exceed balance" # ---------- Product Code ---------- self.balance -= amount # ---------- Postcondition ---------- result = self.balance assert result >= 0, "POST violation: result must be >= 0" return result
PRE violation: amount must not exceed balance account.withdraw(200_000) # Supplierの状態のミスを実行時に検出できる # => AssertionError: PRE violation: status must be 'active' account.freeze() account.withdraw(50_000)
validation error for WithdrawAmount value # Input should be greater than 0 [type=greater_than, input_value=-500, gt=0] amount.withdraw(WithdrawAmount(value=-500)) # 引数とSupplierの関係性のミスを実行時に検出できる(assertでカバー) # => AssertionError: PRE violation: amount must not exceed balance account.withdraw(WithdrawAmount(value=200_000))
+= amount return self.balance # icontractで実行時に検出できる # => icontract.errors.ViolationError: ... # result == self.balance and OLD.bal - self.balance == amount: # OLD was a bunch of OLD values # OLD.bal was 100000 # amount was 50000 # result was 150000 # self.balance was 150000 account.withdraw(50_000)