#36257 qa: assert_equals -> assert_true/assert_false

ReviewabilityReviewsAgreementSize
#36257 hodlinator qa: assert_equals -> assert_true/assert_falseReady0Neutral0 + 644 tests
  • Make boolean checks in functional tests easier to read
  • Reduce cognitive overhead when scanning long test expressions
  • Ready to review
  • No review verdicts recorded
  • Neutral sentiment with no reviewers speaking in favor yet
  • Resolved objection: enforce strict booleans rather than truthiness (l0rinc)
  • Neutral stance without objection (maflcko)
  • 0 lines added or modified outside tests
  • 644 lines added or modified in tests
  • 517 lines removed in total
  • 94 files, 5 commits
Test infrastructure#47 of 54
P4 · cleanup
  • P4 because it is a cosmetic and syntactic cleanup across functional tests
  • Slightly reduces cognitive load when reading tests without expanding coverage or fixing bugs
Reviewability: ReadyStalePaused
Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets
Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs.
Size: lines added or modified outside tests, then in tests; greener = smaller.

Goal

Adds assert_true() and assert_false() helper functions to test_framework/util.py that enforce strict boolean comparison. Converts existing assert_equal(..., True) and assert_equal(..., False) invocations across more than 90 functional test files to the new helpers using a scripted diff.

Problem: Boolean assertions in Python functional tests conventionally used assert_equal(expr, True/False), which is verbose and places the expected boolean literal at the end of long expressions, increasing cognitive load when reading tests.

Evidence of importance:

  • PR description: 'The main point of this change is that assert_true()/assert_false() reduce cognitive tokens when scanning the code (equals to what...?)... assert_true([expression]) is different from plain assert [expression] in that assert is truthy while assert_true requires boolean True.'

Scope: Touches 94 files, but the bulk of the changes are mechanical and executed via scripted diff (sed), preceded by import fixups and an edge-case 3-argument assert_equal fix.

Risk of a mistake: low (tests). A typo or malformed transformation in the scripted diff could cause a functional test to fail or erroneously pass in CI.

Changed since the previous assessment: The commit history has been rebased and organized into preparatory cleanup commits (import fixups and an edge-case fix) followed by the scripted diff and unused-import removal.

Reviewability

Ready

Nothing known that would invalidate a review now.

Agreement

Neutral

objections settled, nobody has spoken for the PR

Thread notes: Initial record. l0rinc caught that the new helpers checked truthiness rather than boolean values, which hodlinator resolved with a push using identity checks; maflcko commented ~0 without objection.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
l0rinc (member)objection, correctnessassert_true and assert_false checked truthiness instead of strict boolean True and Falsefixed · fix pushed · v1, not yet re-checkedansweredyes2026-09-15: 'they're not actually asserting `True`, but rather truthiness'
Status from: 2026-09-15: hodlinator: 'Thanks for catching the accidental degradation in correctness! I originally used != True/!= False but the ruff linter recommended the truthy/falsy variants. `is not` seems to fit the bill without angering ruff.'

Participants:

  • l0rinc (member, objection, 2 statements 2026-09-15 to 2026-09-15): noted assert_true/false checked truthiness rather than boolean identity, and suggested unit tests
  • maflcko (member, neutral, 1 statements 2026-09-16 to 2026-09-16): clarified motivation for assert_equal vs assert; stated ~0 with no objection

Files

1161 lines under test/bench/ci.

  • test/functional/wallet_migration.py +95/-93
  • test/functional/rpc_psbt.py +40/-38
  • test/functional/feature_proxy.py +25/-25
  • test/functional/wallet_importdescriptors.py +26/-24
  • test/functional/wallet_gethdkeys.py +19/-17
  • test/functional/interface_ipc_mining.py +15/-13
  • test/functional/wallet_signer.py +13/-11
  • test/functional/p2p_addr_relay.py +12/-10
  • test/functional/wallet_reorgsrestore.py +12/-10
  • test/functional/feature_fee_estimation.py +11/-9
  • test/functional/p2p_blocksonly.py +10/-10
  • test/functional/wallet_exported_watchonly.py +11/-9
  • test/functional/rpc_rawtransaction.py +10/-8
  • test/functional/wallet_avoidreuse.py +10/-8
  • test/functional/wallet_musig.py +10/-7
  • test/functional/wallet_ancient_migration.py +9/-7
  • test/functional/wallet_backwards_compatibility.py +9/-7
  • test/functional/wallet_createwalletdescriptor.py +9/-7
  • test/functional/wallet_importprunedfunds.py +9/-7
  • test/functional/wallet_listtransactions.py +9/-7
  • test/functional/wallet_keypool.py +8/-7
  • test/functional/rpc_misc.py +8/-6
  • test/functional/wallet_blank.py +7/-6
  • test/functional/wallet_fundrawtransaction.py +7/-6
  • test/functional/feature_assumeutxo.py +7/-5
  • test/functional/interface_usdt_coinselection.py +7/-5
  • test/functional/wallet_abandonconflict.py +7/-5
  • test/functional/wallet_labels.py +6/-6
  • test/functional/wallet_multiwallet.py +7/-5
  • test/functional/rpc_blockchain.py +6/-5
  • test/functional/test_framework/util.py +10/-1
  • test/functional/wallet_descriptor.py +6/-4
  • test/functional/wallet_listsinceblock.py +6/-4
  • test/functional/wallet_miniscript.py +5/-5
  • test/functional/wallet_transactiontime_rescan.py +6/-4
  • test/functional/feature_notifications.py +5/-4
  • test/functional/wallet_signrawtransactionwithwallet.py +5/-4
  • test/functional/p2p_ibd_stalling.py +5/-3
  • test/functional/rpc_net.py +5/-3
  • test/functional/rpc_scantxoutset.py +4/-4
  • test/functional/wallet_assumeutxo.py +5/-3
  • test/functional/wallet_balance.py +5/-3
  • test/functional/wallet_bumpfee.py +5/-3
  • test/functional/wallet_orphanedreward.py +4/-4
  • test/functional/wallet_send.py +5/-3
  • test/functional/mempool_sigoplimit.py +4/-3
  • test/functional/rpc_createmultisig.py +4/-3
  • test/functional/wallet_createwallet.py +4/-3
  • test/functional/feature_addrman.py +3/-3
  • test/functional/feature_maxtipage.py +3/-3
  • test/functional/interface_usdt_utxocache.py +4/-2
  • test/functional/mempool_dust.py +4/-2
  • test/functional/mempool_unbroadcast.py +4/-2
  • test/functional/p2p_compactblocks_blocksonly.py +3/-3
  • test/functional/p2p_tx_download.py +4/-2
  • test/functional/rpc_scanblocks.py +4/-2
  • test/functional/rpc_validateaddress.py +3/-3
  • test/functional/wallet_basic.py +4/-2
  • test/functional/wallet_disable.py +3/-3
  • test/functional/wallet_txn_doublespend.py +4/-2
  • test/functional/feature_minchainwork.py +3/-2
  • test/functional/mining_template_verification.py +3/-2
  • test/functional/wallet_address_types.py +3/-2
  • test/functional/wallet_derivehdkey.py +3/-2
  • test/functional/wallet_listrawtransactions.py +3/-2
  • test/functional/wallet_listreceivedby.py +3/-2
  • test/functional/feature_discover.py +2/-2
  • test/functional/p2p_compactblocks_hb.py +2/-2
  • test/functional/rpc_openrpc.py +2/-2
  • test/functional/wallet_deprecated_rbf.py +2/-2
  • test/functional/feature_block.py +2/-1
  • test/functional/feature_rbf.py +2/-1
  • test/functional/interface_rest.py +2/-1
  • test/functional/interface_usdt_mempool.py +2/-1
  • test/functional/mempool_accept.py +2/-1
  • test/functional/mempool_datacarrier.py +2/-1
  • test/functional/p2p_disconnect_ban.py +2/-1
  • test/functional/p2p_segwit.py +2/-1
  • test/functional/p2p_sendheaders.py +2/-1
  • test/functional/p2p_unrequested_blocks.py +2/-1
  • test/functional/rpc_gettxspendingprevout.py +2/-1
  • test/functional/rpc_signer.py +2/-1
  • test/functional/rpc_signrawtransactionwithkey.py +2/-1
  • test/functional/test_framework/test_framework.py +2/-1
  • test/functional/test_framework/wallet.py +2/-1
  • test/functional/tool_wallet.py +2/-1
  • test/functional/wallet_anchor.py +2/-1
  • test/functional/wallet_encryption.py +2/-1
  • test/functional/wallet_hd.py +2/-1
  • test/functional/wallet_miniscript_decaying_multisig_descriptor_psbt.py +2/-1
  • test/functional/wallet_resendwallettransactions.py +2/-1
  • test/functional/wallet_sendall.py +2/-1
  • test/functional/wallet_simulaterawtx.py +2/-1
  • test/functional/wallet_txn_clone.py +2/-1

Card

The short text the ranking pass compares across PRs.

This PR adds assert_true() and assert_false() helper functions to the functional test framework and migrates existing assert_equal calls comparing against boolean literals across the test suite via a scripted diff. It improves test code readability and ergonomics while ensuring strict boolean identity rather than truthiness. Importance is low because it is an internal test framework cleanup that alters neither node behavior nor test coverage.

Data

dossier JSON · extract JSON · model ledger, generated 2026-10-03T01:18, confidence high, input hash 2c6756f49be98918
thread read through 2026-09-16 (6 statements), head 77e6026a96
Discussion read under schema 1 rules: suggestions and questions may be missing, and an objection may combine several harms (schema history).
labels: Tests

Categories

Test infrastructure

P4 · cleanup

This PR is an internal test framework cleanup to reduce cognitive load and enforce boolean assertions. The author notes that 'the main point of this change is that assert_true()/assert_false() reduce cognitive tokens when scanning the code'; such cosmetic and syntactic cleanups rank at the bottom of the testing hierarchy.

Membership: Labeled 'Tests' and modifies test_framework/util.py by adding assert_true() and assert_false() helper functions.

Factors: security/stability 0, bug 0, performance 0, user value 0, leverage 0