{"id":40380,"date":"2023-08-17T14:35:00","date_gmt":"2023-08-17T18:35:00","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=40380"},"modified":"2023-10-11T16:44:15","modified_gmt":"2023-10-11T20:44:15","slug":"how-to-automate-memory-leak-detection-with-xctest","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2023\/08\/17\/how-to-automate-memory-leak-detection-with-xctest\/","title":{"rendered":"How to Automate Memory Leak Detection With XCTest"},"content":{"rendered":"<p><a href=\"https:\/\/qualitycoding.org\/swift-memory-leak-detection-xctest\/\">Dan Torres<\/a>:<\/p>\n<blockquote cite=\"https:\/\/qualitycoding.org\/swift-memory-leak-detection-xctest\/\"><p>Inside the <code>addTearDownBlock<\/code>, we can assert if <code>sut<\/code> and <code>spy<\/code> are deallocated by asserting if they&rsquo;re <code>nil<\/code>. We hold <code>sut<\/code> and <code>spy<\/code> with weak references so that they won&rsquo;t be strongly retained when executing the block. <\/p><p>[&#8230;]<\/p><p>But adding this block to all your tests may reduce readability. So we can add an extension to <code>XCTestCase<\/code>, which will allow us to use it in any test. We would also add the file and line so the failure message can be at the exact line and file where the test failed.<\/p><\/blockquote>\n<p>I&rsquo;ve found this sort of thing very helpful. I don&rsquo;t recall why I didn&rsquo;t use weak closure captures. Instead, I&rsquo;ve been using associated objects that fulfill <code>XCTestExpectation<\/code>s when they&rsquo;re deallocated. Sometimes it takes a run loop cycle before objects are deallocated.<\/p>\n<p>In order for this to work, you have to be careful of when you and Cocoa autorelease objects. For example, creating an <code>NSWindow<\/code> or setting its title will end up extending the life of its view controller. So does changing the selected tab view item or some other tab view properties. You may think you&rsquo;re avoiding leaks by using <code>NSHashTable<\/code> to store weak references, but adding or reading the objects causes them to be retained and then autoreleased.<\/p>\n\n<p>See also: <a href=\"https:\/\/swiftrocks.com\/unit-testing-weak-references--deallocation-in-swift\">Bruno Rocha<\/a>, <a href=\"https:\/\/paul-samuels.com\/blog\/2018\/11\/20\/unit-testing-retain-cycles\/\">Paul Samuels<\/a>, <a href=\"https:\/\/medium.com\/@johnsundell\/using-unit-tests-to-identify-avoid-memory-leaks-in-swift-607c97465b62\">John Sundell<\/a>.<\/p>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2023\/08\/04\/avoiding-implicit-retain-cycles-when-using-swift-function-references\/\">Avoiding Implicit Retain Cycles When Using Swift Function References<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2018\/03\/23\/dealing-with-weak-in-closure-based-delegation\/\">Dealing With Weak in Closure-based Delegation<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2017\/04\/12\/automatic-memory-leak-detection-on-ios\/\">Automatic Memory Leak Detection on iOS<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Dan Torres: Inside the addTearDownBlock, we can assert if sut and spy are deallocated by asserting if they&rsquo;re nil. We hold sut and spy with weak references so that they won&rsquo;t be strongly retained when executing the block. [&#8230;]But adding this block to all your tests may reduce readability. So we can add an extension [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2023-08-17T18:35:02Z","apple_news_api_id":"21ffd36d-1efd-4db9-81a1-ec940b2f9de8","apple_news_api_modified_at":"2023-08-17T18:35:03Z","apple_news_api_revision":"AAAAAAAAAAD\/\/\/\/\/\/\/\/\/\/w==","apple_news_api_share_url":"https:\/\/apple.news\/AIf_TbR79TbmBoeyUCy-d6A","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[55,69,30,2223,571,71,901,268,226],"class_list":["post-40380","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-arc","tag-cocoa","tag-mac","tag-macos-13-ventura","tag-memory-management","tag-programming","tag-swift-programming-language","tag-testing","tag-xcode"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/40380","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=40380"}],"version-history":[{"count":1,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/40380\/revisions"}],"predecessor-version":[{"id":40381,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/40380\/revisions\/40381"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=40380"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=40380"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=40380"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}