CINXE.COM
Google Testing Blog: 2017
<!DOCTYPE html> <html class='v2 list-page' dir='ltr' itemscope='' itemtype='http://schema.org/Blog' lang='en' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'> <head> <link href='https://www.blogger.com/static/v1/widgets/3566091532-css_bundle_v2.css' rel='stylesheet' type='text/css'/> <title> Google Testing Blog: 2017 </title> <meta content='width=device-width, height=device-height, minimum-scale=1.0, initial-scale=1.0, user-scalable=0' name='viewport'/> <meta content='IE=Edge' http-equiv='X-UA-Compatible'/> <meta content='Google Testing Blog' property='og:title'/> <meta content='en_US' property='og:locale'/> <meta content='https://testing.googleblog.com/2017/' property='og:url'/> <meta content='Google Testing Blog' property='og:site_name'/> <!-- Twitter Card properties --> <meta content='Google Testing Blog' property='og:title'/> <meta content='summary' name='twitter:card'/> <meta content='@googletesting' name='twitter:creator'/> <link href='https://fonts.googleapis.com/css?family=Roboto:400italic,400,500,500italic,700,700italic' rel='stylesheet' type='text/css'/> <link href='https://fonts.googleapis.com/icon?family=Material+Icons' rel='stylesheet'/> <script src='https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js' type='text/javascript'></script> <!-- End --> <style id='page-skin-1' type='text/css'><!-- /* <Group description="Header Color" selector="header"> <Variable name="header.background.color" description="Header Background" type="color" default="#ffffff"/> </Group> */ .header-outer { border-bottom: 1px solid #e0e0e0; background: #ffffff; } html, .Label h2, #sidebar .rss a, .BlogArchive h2, .FollowByEmail h2.title, .widget .post h2 { font-family: Roboto, sans-serif; } .plusfollowers h2.title, .post h2.title, .widget h2.title { font-family: Roboto, sans-serif; } .widget-item-control { height: 100%; } .widget.Header, #header { position: relative; height: 100%; width: 100%; } } .widget.Header .header-logo1 { float: left; margin-right: 15px; padding-right: 15px; border-right: 1px solid #ddd; } .header-title h2 { color: rgba(0,0,0,.54); display: inline-block; font-size: 40px; font-family: Roboto, sans-serif; font-weight: normal; line-height: 48px; vertical-align: top; } .header-inner { background-repeat: no-repeat; background-position: right 0px; } .post-author, .byline-author { font-size: 14px; font-weight: normal; color: #757575; color: rgba(0,0,0,.54); } .post-content .img-border { border: 1px solid rgb(235, 235, 235); padding: 4px; } .header-title a { text-decoration: none !important; } pre { border: 1px solid #bbbbbb; margin-top: 1em 0 0 0; padding: 0.99em; overflow-x: auto; overflow-y: auto; } pre, code { font-size: 9pt; background-color: #fafafa; line-height: 125%; font-family: monospace; } pre, code { color: #060; font: 13px/1.54 "courier new",courier,monospace; } .header-left .header-logo1 { width: 128px !important; } .header-desc { line-height: 20px; margin-top: 8px; } .fb-custom img, .twitter-custom img, .gplus-share img { cursor: pointer; opacity: 0.54; } .fb-custom img:hover, .twitter-custom img:hover, .gplus-share img:hover { opacity: 0.87; } .fb-like { width: 80px; } .post .share { float: right; } #twitter-share{ border: #CCC solid 1px; border-radius: 3px; background-image: -webkit-linear-gradient(top,#ffffff,#dedede); } .twitter-follow { background: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSPSElBOH0lQ-yG1UMSLWe_pq9gZ9DT-0xhhjwadPeQt1WAHCnDYvERUcHBadwN6NcdtZCJu-F0fLqO6_PnV2iWDxnun1R_ii8saOztKUI6GA6zc2FNkjkcfTDlPzaINdbYhPw7Q/s1600/twitter-bird.png) no-repeat left center; padding-left: 18px; font: normal normal normal 11px/18px 'Helvetica Neue',Arial,sans-serif; font-weight: bold; text-shadow: 0 1px 0 rgba(255,255,255,.5); cursor: pointer; margin-bottom: 10px; } .twitter-fb { padding-top: 2px; } .fb-follow-button { background: -webkit-linear-gradient(#4c69ba, #3b55a0); background: -moz-linear-gradient(#4c69ba, #3b55a0); background: linear-gradient(#4c69ba, #3b55a0); border-radius: 2px; height: 18px; padding: 4px 0 0 3px; width: 57px; border: #4c69ba solid 1px; } .fb-follow-button a { text-decoration: none !important; text-shadow: 0 -1px 0 #354c8c; text-align: center; white-space: nowrap; font-size: 11px; color: white; vertical-align: top; } .fb-follow-button a:visited { color: white; } .fb-follow { padding: 0px 5px 3px 0px; width: 14px; vertical-align: bottom; } .gplus-wrapper { margin-top: 3px; display: inline-block; vertical-align: top; } .twitter-custom, .gplus-share { margin-right: 12px; } .fb-follow-button{ margin: 10px auto; } /** CUSTOM CODE **/ /* Make the page title smaller */ .header-inner { height: 120px !important; } /* Make the post titles look like the links that they are */ .post .title a { color: #4184F3 !important; } /* Set a normal line height in post text */ .post .post-content { line-height: 1.4 !important; } .post .post-content li { line-height: 1.4 !important; } /* Custom table class used in some posts */ .my-bordered-table { border-collapse: collapse; border: 1px solid black; } .my-bordered-table th, .my-bordered-table td { border: 1px solid black; padding: 5px; } --></style> <style id='template-skin-1' type='text/css'><!-- .header-outer { clear: both; } .header-inner { margin: auto; padding: 0px; } .footer-outer { background: #f5f5f5; clear: both; margin: 0; } .footer-inner { margin: auto; padding: 0px; } .footer-inner-2 { /* Account for right hand column elasticity. */ max-width: calc(100% - 248px); } .google-footer-outer { clear: both; } .cols-wrapper, .google-footer-outer, .footer-inner, .header-inner { max-width: 978px; margin-left: auto; margin-right: auto; } .cols-wrapper { margin: auto; clear: both; margin-top: 60px; margin-bottom: 60px; overflow: hidden; } .col-main-wrapper { float: left; width: 100%; } .col-main { margin-right: 278px; max-width: 660px; } .col-right { float: right; width: 248px; margin-left: -278px; } /* Tweaks for layout mode. */ body#layout .google-footer-outer { display: none; } body#layout .header-outer, body#layout .footer-outer { background: none; } body#layout .header-inner { height: initial; } body#layout .cols-wrapper { margin-top: initial; margin-bottom: initial; } --></style> <!-- start all head --> <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/> <meta content='blogger' name='generator'/> <link href='https://testing.googleblog.com/favicon.ico' rel='icon' type='image/x-icon'/> <link href='https://testing.googleblog.com/2017/' rel='canonical'/> <link rel="alternate" type="application/atom+xml" title="Google Testing Blog - Atom" href="https://testing.googleblog.com/feeds/posts/default" /> <link rel="alternate" type="application/rss+xml" title="Google Testing Blog - RSS" href="https://testing.googleblog.com/feeds/posts/default?alt=rss" /> <link rel="service.post" type="application/atom+xml" title="Google Testing Blog - Atom" href="https://www.blogger.com/feeds/15045980/posts/default" /> <!--Can't find substitution for tag [blog.ieCssRetrofitLinks]--> <meta content='https://testing.googleblog.com/2017/' property='og:url'/> <meta content='Google Testing Blog' property='og:title'/> <meta content='' property='og:description'/> <!-- end all head --> <base target='_self'/> <style> html { font-family: Roboto, sans-serif; -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; } body { padding: 0; /* This ensures that the scroll bar is always present, which is needed */ /* because content render happens after page load; otherwise the header */ /* would "bounce" in-between states. */ min-height: 150%; } h2 { font-size: 20px; } h1, h2, h3, h4, h5 { line-height: 2em; } html, h4, h5, h6 { font-size: 17px; } h3 { font-size: 18px !important; } a, a:visited { color: #4184F3; text-decoration: none; } a:focus, a:hover, a:active { text-decoration: none; } .Header { margin-top: 15px; } .Header h1 { font-size: 32px; font-weight: 300; line-height: 32px; height: 42px; } .header-inner .Header .titlewrapper { padding: 0; margin-top: 30px; } .header-inner .Header .descriptionwrapper { padding: 0; margin: 0; } .cols-wrapper { margin-top: 56px; } .header-outer, .cols-wrapper, .footer-outer, .google-footer-outer { padding: 0 60px; } .header-inner { height: 256px; position: relative; } html, .header-inner a { color: #212121; color: rgba(0,0,0,.87); } .header-inner .google-logo { display: inline-block; background-size: contain; z-index: 1; height: 46px; overflow: hidden; margin-top: 4px; margin-right: 8px; } .header-left { position: absolute; top: 50%; -webkit-transform: translateY(-50%); transform: translateY(-50%); margin-top: 12px; width: 100%; } .google-logo { margin-left: -4px; } #google-footer { position: relative; font-size: 13px; list-style: none; text-align: right; } #google-footer a { color: #444; } #google-footer ul { margin: 0; padding: 0; height: 144px; line-height: 144px; } #google-footer ul li { display: inline; } #google-footer ul li:before { color: #999; content: "\00b7"; font-weight: bold; margin: 5px; } #google-footer ul li:first-child:before { content: ''; } #google-footer .google-logo-dark { left: 0; margin-top: -16px; position: absolute; top: 50%; } /** Sitemap links. **/ .footer-inner-2 { font-size: 14px; padding-top: 42px; padding-bottom: 74px; } .footer-inner-2 .HTML h2 { color: #212121; color: rgba(0,0,0,.87); font-size: 14px; font-weight: 500; padding-left: 0; margin: 10px 0; } .footer-inner-2 .HTML ul { font-weight: normal; list-style: none; padding-left: 0; } .footer-inner-2 .HTML li { line-height: 24px; padding: 0; } .footer-inner-2 li a { color: rgba(65,132,243,.87); } /** Archive widget. **/ .BlogArchive { font-size: 13px; font-weight: normal; } .BlogArchive .widget-content { display: none; } .BlogArchive h2, .Label h2 { color: #4184F3; text-decoration: none; } .BlogArchive .hierarchy li { display: inline-block; } /* Specificity needed here to override widget CSS defaults. */ .BlogArchive #ArchiveList ul li, .BlogArchive #ArchiveList ul ul li { padding-left: 0; text-indent: 0; } .BlogArchive .intervalToggle { cursor: pointer; } .BlogArchive .expanded .intervalToggle .new-toggle { -ms-transform: rotate(180deg); transform: rotate(180deg); } .BlogArchive .new-toggle { float: right; padding-top: 3px; opacity: 0.87; } #ArchiveList { text-transform: uppercase; } #ArchiveList .expanded > ul:last-child { margin-bottom: 16px; } #ArchiveList .archivedate { width: 100%; } /* Months */ .BlogArchive .items { max-width: 150px; margin-left: -4px; } .BlogArchive .expanded .items { margin-bottom: 10px; overflow: hidden; } .BlogArchive .items > ul { float: left; height: 32px; } .BlogArchive .items a { padding: 0 4px; } .Label { font-size: 13px; font-weight: normal; } .sidebar-icon { display: inline-block; width: 24px; height: 24px; vertical-align: middle; margin-right: 12px; margin-top: -1px } .Label a { margin-right: 4px; } .Label .widget-content { display: none; } .FollowByEmail { font-size: 13px; font-weight: normal; } .FollowByEmail h2 { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAALCAYAAACZIGYHAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAUBJREFUeNrMkSGLAlEUhb+ZB4JFi8mx2cz+ApvhRUGTcUCrNqNJDYIi+DO0GUwmQXDK2DSIoGgZcSaIjDrzwrK4ssvChj1w0733O+fdp+m6PozH4yQSCfb7Pa7r8pOi0SjJZBLP8zgej4gAIMvlMuPxmADIYrHger1+C6lUKmo+NJ/NZojb7SZDWiwWo1qtks1msW2bw+HwZdkwDHq9HvV6nel0SqvVYrvdIh6Ph3Qch+VyqRYLhQJSSjRNw7IsfN9XgGKxSLfbJZfL0e/3aTabrFYr7vc7IujLcOh8PqunrNdr0uk0pVKJVCpFJBJRgEajweVyod1uMxgM2O12BAGUgRbU8DV2JpOhVquRz+cRQii3+XxOp9NRN3jVR5LPOp1OjEYjlSL8hclkgmmabDabt4d+m+S30vkD/R/IU4ABAPTZgnZdmG/PAAAAAElFTkSuQmCC"); background-repeat: no-repeat; background-position: 0 50%; text-indent: 30px; } .FollowByEmail .widget-content { display: none; } .searchBox input { border: 1px solid #eee; color: #212121; color: rgba(0,0,0,.87); font-size: 14px; padding: 8px 8px 8px 40px; width: 164px; font-family: Roboto, sans-serif; background: url("https://www.gstatic.com/images/icons/material/system/1x/search_grey600_24dp.png") 8px center no-repeat; } .searchBox ::-webkit-input-placeholder { /* WebKit, Blink, Edge */ color: rgba(0,0,0,.54); } .searchBox :-moz-placeholder { /* Mozilla Firefox 4 to 18 */ color: #000; opacity: 0.54; } .searchBox ::-moz-placeholder { /* Mozilla Firefox 19+ */ color: #000; opacity: 0.54; } .searchBox :-ms-input-placeholder { /* Internet Explorer 10-11 */ color: #757575; } .widget-item-control { margin-top: 0px; } .section { margin: 0; padding: 0; } #sidebar-top { border: 1px solid #eee; } #sidebar-top > div { margin: 16px 0; } .widget ul { line-height: 1.6; } /*main post*/ .post { margin-bottom:30px; } #main .post .title { margin: 0; } #main .post .title a { color: #212121; color: rgba(0,0,0,.87); font-weight: normal; font-size: 24px; } #main .post .title a:hover { text-decoration:none; color:#4184F3; } .message, #main .post .post-header { margin: 0; padding: 0; } #main .post .post-header .caption, #main .post .post-header .labels-caption, #main .post .post-footer .caption, #main .post .post-footer .labels-caption { color: #444; font-weight: 500; } #main .tr-caption-container td { text-align: left; } #main .post .tr-caption { color: #757575; color: rgba(0,0,0,.54); display: block; max-width: 560px; padding-bottom: 20px; } #main .post .tr-caption-container { line-height: 24px; margin: -1px 0 0 0 !important; padding: 4px 0; text-align: left; } #main .post .post-header .published{ font-size:11px; font-weight:bold; } .post-header .publishdate { font-size: 17px; font-weight:normal; color: #757575; color: rgba(0,0,0,.54); } #main .post .post-footer{ font-size:12px; padding-bottom: 21px; } .label-footer { margin-bottom: 12px; margin-top: 12px; } .comment-img { margin-right: 16px; opacity: 0.54; vertical-align: middle; } #main .post .post-header .published { margin-bottom: 40px; margin-top: -2px; } .post .post-content { color: #212121; color: rgba(0,0,0,.87); font-size: 17px; margin: 25px 0 36px 0; line-height: 32px; word-wrap: break-word; } .post-body .post-content ul, .post-body .post-content ol { margin: 16px 0; padding: 0 48px; } .post-summary { display: none; } /* Capture section headers. */ .post-content br + br + b, .post-content .space + .space + b, .post-content .separator + b { display: inline-block; margin-bottom: 8px; margin-top: 24px; } .post-content li { line-height: 32px; } /* Override all post images/videos to left align. */ .post-content .separator, .post-content > div { text-align: left; } .post-content .separator > a, .post-content .separator > span { margin-left: 0 !important; } .post-content img { max-width: 100%; } .post-content .tr-caption-container img { margin-bottom: 12px; } .post-content iframe, .post-content embed { max-width: 100%; } .post-content .carousel-container { margin-bottom: 48px; } #main .post-content b { font-weight: 500; } /* These are the main paragraph spacing tweaks. */ #main .post-content br { content: ' '; display: block; padding: 4px; } .post-content .space { display: block; height: 8px; } .post-content iframe + .space, .post-content iframe + br { padding: 0 !important; } #main .post .jump-link { margin-bottom:10px; } .post-content img, .post-content iframe { margin: 30px 0 20px 0; } .post-content > img:first-child, .post-content > iframe:first-child { margin-top: 0; } .col-right .section { padding: 0 16px; } #aside { background:#fff; border:1px solid #eee; border-top: 0; } #aside .widget { margin:0; } #aside .widget h2, #ArchiveList .toggle + a.post-count-link { color: #212121; color: rgba(0,0,0,.87); font-weight: 400 !important; margin: 0; } #ArchiveList .toggle { float: right; } #ArchiveList .toggle .material-icons { padding-top: 4px; } #sidebar .tab { cursor: pointer; } #sidebar .tab .arrow { display: inline-block; float: right; } #sidebar .tab .icon { display: inline-block; vertical-align: top; height: 24px; width: 24px; margin-right: 13px; margin-left: -1px; margin-top: 1px; color: #757575; color: rgba(0,0,0,.54); } #sidebar .widget-content > :first-child { padding-top: 8px; } #sidebar .active .tab .arrow { -ms-transform: rotate(180deg); transform: rotate(180deg); } #sidebar .arrow { color: #757575; color: rgba(0,0,0,.54); } #sidebar .widget h2 { font-size: 14px; line-height: 24px; display: inline-block; } #sidebar .widget .BlogArchive { padding-bottom: 8px; } #sidebar .widget { border-bottom: 1px solid #eee; box-shadow: 0px 1px 0 white; margin-bottom: 0; padding: 14px 0; min-height: 20px; } #sidebar .widget:last-child { border-bottom: none; box-shadow: none; margin-bottom: 0; } #sidebar ul { margin: 0; padding: 0; } #sidebar ul li { list-style:none; padding:0; } #sidebar ul li a { line-height: 32px; } #sidebar .archive { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAYCAYAAADzoH0MAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAE1JREFUeNpiNDY23s9AAWBioBCwYBM8c+YMVsUmJibEGYBNMS5DaeMFfDYSZQA2v9I3FrB5AZeriI4FmnrBccCT8mhmGs1MwyAzAQQYAKEWG9zm9QFEAAAAAElFTkSuQmCC"); height: 24px; line-height: 24px; padding-left: 30px; } #sidebar .labels { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAUxJREFUeNpiNDY23s9AAMycOfM7UF05kHkZmzwTMkdSUhKrIcXFxZy3bt3qBjIN8RrS09PDsHnzZjCNDr58+cKQlpbGDjSoHcg1w2oIyAUODg5gARCNzUVIBrUCuVYYhjx//pzhwIEDYAEQDeJjA1CDWIAGNQK59jBxRuSABbkAlwHIgIeHh2HWrFn/1NTU2oDcvSgBS4wBSC5iArqoCsj1YGIgEyAZVMoEchqlBjEB/cZAiUHg2AEGznpKDAImxOeM////B4VLKtBvEUCngZ1ILKivr3/u6+ubBzJAGZQ9gC5aQoqLgAY8BhkAZL4BuQQkxgXE34A4BuiiZEIuAhrwEGhAEZD5DpzYoIaA2UAM4kQADUrHZRDUgAIg8wO2XAwzbQXQa5OweQ1owB10AyA6gS7BgX1u3ry5397eHow3bdo0EyjGi00tQIABANPgyAH1q1eaAAAAAElFTkSuQmCC"); height: 20px; line-height: 20px; padding-left: 30px; } #sidebar .rss a { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAX5JREFUeNqsVDGSgkAQHL2rIiIikohIc/EBRkbwAIwuwgfwAXiAD9AHSI7kEkECRCb6AIyINDLx7K0aa6kT7uq0q7YYtnZ7umdnt7darXbr9Zpegeu61DNNc0dvwCcH4/GYJpMJnc9nOhwOVJbl/4hAAokMECZJQtvt9k+kH7qufyEYDAakqqqYxFdRFBqNRmTbNg2HQ0rTlK7XayvR0xqBdDqdkuM4dE/0ULhYLOh4PHYrknG5XGi/31MYhuL/nkwonM1mlGUZ1XXdrsiyLGEDhY7juJEZ1u5tIixDGdYhmYw+B7CAzPP5nDabjdgIAgCksMX1832/3drtdqPT6SQWapomiGEFNkDEdpDMMAzK81ys/7XYy+XyoQgq2WoURSIJ2iIIgp/WZCCTvFm2wgeAU31aI3Q2GhIDMeB53qPYPIcm5VrxXIOIOxsDMStjVawAc1VViRgN22lNBiuQN3GR+SY07hpOoStmFQAKXRRFY93bnpG+fONfedi+BRgAbkS8Fxp7QQIAAAAASUVORK5CYII="); } #sidebar .subscription a { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAALCAYAAACZIGYHAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAUBJREFUeNrMkSGLAlEUhb+ZB4JFi8mx2cz+ApvhRUGTcUCrNqNJDYIi+DO0GUwmQXDK2DSIoGgZcSaIjDrzwrK4ssvChj1w0733O+fdp+m6PozH4yQSCfb7Pa7r8pOi0SjJZBLP8zgej4gAIMvlMuPxmADIYrHger1+C6lUKmo+NJ/NZojb7SZDWiwWo1qtks1msW2bw+HwZdkwDHq9HvV6nel0SqvVYrvdIh6Ph3Qch+VyqRYLhQJSSjRNw7IsfN9XgGKxSLfbJZfL0e/3aTabrFYr7vc7IujLcOh8PqunrNdr0uk0pVKJVCpFJBJRgEajweVyod1uMxgM2O12BAGUgRbU8DV2JpOhVquRz+cRQii3+XxOp9NRN3jVR5LPOp1OjEYjlSL8hclkgmmabDabt4d+m+S30vkD/R/IU4ABAPTZgnZdmG/PAAAAAElFTkSuQmCC"); } #sidebar-bottom { background: #f5f5f5; border-top:1px solid #eee; } #sidebar-bottom .widget { border-bottom: 1px solid #e0e0e0; padding: 15px 0; text-align: center; } #sidebar-bottom > div:last-child { border-bottom: 0; } #sidebar-bottom .text { line-height: 20px; } /* Home, forward, and backward pagination. */ .blog-pager { border-top : 1px #e0e0e0 solid; padding-top: 10px; margin-top: 15px; text-align: right !important; } #blog-pager { margin-botom: 0; margin-top: -14px; padding: 16px 0 0 0; } #blog-pager a { display: inline-block; } .blog-pager i.disabled { opacity: 0.2 !important; } .blog-pager i { color: black; margin-left: 16px; opacity: 0.54; } .blog-pager i:hover, .blog-pager i:active { opacity: 0.87; } #blog-pager-older-link, #blog-pager-newer-link { float: none; } .gplus-profile { background-color: #fafafa; border: 1px solid #eee; overflow: hidden; width: 212px; } .gplus-profile-inner { margin-left: -1px; margin-top: -1px; } /* Sidebar follow buttons. */ .followgooglewrapper { padding: 12px 0 0 0; } .loading { visibility: hidden; } .detail-page .post-footer .cmt_iframe_holder { padding-top: 40px !important; } /** Desktop **/ @media (max-width: 900px) { .col-right { display: none; } .col-main { margin-right: 0; min-width: initial; } .footer-outer { display: none; } .cols-wrapper { min-width: initial; } .google-footer-outer { background-color: #f5f5f5; } } /** Tablet **/ @media (max-width: 712px) { .header-outer, .cols-wrapper, .footer-outer, .google-footer-outer { padding: 0 40px; } } /* An extra breakpoint accommodating for long blog titles. */ @media (max-width: 600px) { .header-left { height: 100%; position: initial; top: inherit; margin-top: 0; -webkit-transform: initial; transform: initial; } .header-title { margin-top: 18px; } .header-inner { height: auto; margin-bottom: 32px; margin-top: 32px; } .header-desc { margin-top: 12px; } .header-inner .google-logo { height: 40px; margin-top: 3px; } .header-inner .google-logo img { height: 42px; } .header-title h2 { font-size: 32px; line-height: 40px; } } /** Mobile/small desktop window; also landscape. **/ @media (max-width: 480px), (max-height: 480px) { .header-outer, .cols-wrapper, .footer-outer, .google-footer-outer { padding: 0 16px; } .cols-wrapper { margin-top: 0; } .post-header .publishdate, .post .post-content { font-size: 16px; } .post .post-content { line-height: 28px; margin-bottom: 30px; } .post { margin-top: 30px; } .byline-author { display: block; font-size: 12px; line-height: 24px; margin-top: 6px; } #main .post .title a { font-weight: 500; color: #4c4c4c; color: rgba(0,0,0,.70); } #main .post .post-header { padding-bottom: 12px; } #main .post .post-header .published { margin-bottom: -8px; margin-top: 3px; } .post .read-more { display: block; margin-top: 14px; } .post .tr-caption { font-size: 12px; } #main .post .title a { font-size: 20px; line-height: 30px; } .post-content iframe { /* iframe won't keep aspect ratio when scaled down. */ max-height: 240px; } .post-content .separator img, .post-content .tr-caption-container img, .post-content iframe { margin-left: -16px; max-width: inherit; width: calc(100% + 32px); } .post-content table, .post-content td { width: 100%; } #blog-pager { margin: 0; padding: 16px 0; } /** List page tweaks. **/ .list-page .post-original { display: none; } .list-page .post-summary { display: block; } .list-page .comment-container { display: none; } .list-page #blog-pager { padding-top: 0; border: 0; margin-top: -8px; } .list-page .label-footer { display: none; } .list-page #main .post .post-footer { border-bottom: 1px solid #eee; margin: -16px 0 0 0; padding: 0 0 20px 0; } .list-page .post .share { display: none; } /** Detail page tweaks. **/ .detail-page .post-footer .cmt_iframe_holder { padding-top: 32px !important; } .detail-page .label-footer { margin-bottom: 0; } .detail-page #main .post .post-footer { padding-bottom: 0; } .detail-page #comments { display: none; } } [data-about-pullquote], [data-is-preview], [data-about-syndication] { display: none; } </style> <noscript> <style> .loading { visibility: visible }</style> </noscript> <!-- Google tag (gtag.js) --> <script async='true' src='https://www.googletagmanager.com/gtag/js?id=G-838ZCPQWM6'></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-838ZCPQWM6'); </script> <link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=15045980&zx=4804591f-4b0d-457d-91c1-fd6e244b873a' media='none' onload='if(media!='all')media='all'' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=15045980&zx=4804591f-4b0d-457d-91c1-fd6e244b873a' rel='stylesheet'/></noscript> <meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/> <meta name='google-adsense-platform-domain' content='blogspot.com'/> </head> <body> <script type='text/javascript'> //<![CDATA[ var axel = Math.random() + ""; var a = axel * 10000000000000; document.write('<iframe src="https://2542116.fls.doubleclick.net/activityi;src=2542116;type=gblog;cat=googl0;ord=ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>'); //]]> </script> <noscript> <img alt='' height='1' src='https://ad.doubleclick.net/ddm/activity/src=2542116;type=gblog;cat=googl0;ord=1?' width='1'/> </noscript> <!-- Header --> <div class='header-outer'> <div class='header-inner'> <div class='section' id='header'><div class='widget Header' data-version='1' id='Header1'> <div class='header-left'> <div class='header-title'> <a class='google-logo' href='https://testing.googleblog.com/'> <img height='50' src='https://www.gstatic.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png'/> </a> <a href='/.'> <h2> Testing Blog </h2> </a> </div> <div class='header-desc'> </div> </div> </div></div> </div> </div> <!-- all content wrapper start --> <div class='cols-wrapper loading'> <div class='col-main-wrapper'> <div class='col-main'> <div class='section' id='main'><div class='widget Blog' data-version='1' id='Blog1'> <div class='post' data-id='3797894023961037485' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2017/12/testing-on-toilet-only-verify-state.html' itemprop='url' title='Testing on the Toilet: Only Verify State-Changing Method Calls'> Testing on the Toilet: Only Verify State-Changing Method Calls </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Monday, December 11, 2017 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <i><span style="font-family: "times" , "times new roman" , serif;">This article was adapted from a <a href="http://googletesting.blogspot.com/2007/01/introducing-testing-on-toilet.html">Google Testing on the Toilet</a> (TotT) episode. You can download a <a href="https://docs.google.com/document/d/1A0USfjPsmS4fSpgCfunBab8azRIPDTIKi-wRZD1K58k/edit?usp=sharing" rel="nofollow">printer-friendly version</a> of this TotT episode and post it in your office.</span></i><br /> <i><br /></i><span style="font-family: "times" , "times new roman" , serif;"> By Dillon Bly and Andrew Trenk</span><br /> <span style="font-family: "times" , "times new roman" , serif;"><br /></span> <span style="font-family: "times" , "times new roman" , serif;">Which lines can be safely removed from this test?</span><br /> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #f4cccc; vertical-align: top; width: 607px;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;">@Test public void addPermissionToDatabase() { new UserAuthorizer(<span style="font-weight: bold;">mockUserService</span>, <span style="font-weight: bold;">mockPermissionDb</span>).grantPermission(USER, READ_ACCESS); </span></pre> <pre style="background-color: #f4cccc; border: 0px; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;"> </span></pre> <pre style="background-color: #f4cccc; border: 0px; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="color: black; font-family: "consolas" , "courier new" , "courier" , monospace;"> <span style="color: blue;">// The test will fail if any of these methods is not called.</span> verify(<span style="font-weight: bold;">mockUserService</span>).isUserActive(USER); verify(<span style="font-weight: bold;">mockPermissionDb</span>).getPermissions(USER); verify(<span style="font-weight: bold;">mockPermissionDb</span>).isValidPermission(READ_ACCESS); verify(<span style="font-weight: bold;">mockPermissionDb</span>).addPermission(USER, READ_ACCESS); }</span></pre> </td></tr> </tbody></table> </div> <span style="font-size: 12pt; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span id="docs-internal-guid-b50ac775-4768-13da-eaac-0ee595ad284f" style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">The answer is that </span><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">the calls to verify the non-state-changing methods can be removed</span><span style="vertical-align: baseline; white-space: pre-wrap;">.</span></span><br /> <span style="font-size: 12pt; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span id="docs-internal-guid-b50ac775-4768-4d70-7394-a597c452b64e" style="font-family: "times" , "times new roman" , serif;"><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Method calls on another object fall into one of two categories</span><span style="vertical-align: baseline; white-space: pre-wrap;">:</span></span><br /> <ul> <li><span style="white-space: pre-wrap;"><span id="docs-internal-guid-b50ac775-4768-8635-e00b-dd78588a4f61"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; font-weight: 700; vertical-align: baseline;">State-changing</span><span style="vertical-align: baseline;">: methods that have side effects and change the world outside the code under test, </span></span><span style="vertical-align: baseline;"><span style="font-family: "times" , "times new roman" , serif;">e.g.,</span> </span></span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">sendEmail()</span></span><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline;">,</span><span style="vertical-align: baseline;"> </span></span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">saveRecord()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;">, </span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">logAccess()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;">.</span></span></span></li> <li><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-b50ac775-4768-c934-c2fa-bd06b2961ff3"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; font-weight: 700; vertical-align: baseline;">Non-state-changing</span><span style="font-style: italic; vertical-align: baseline;">:</span><span style="vertical-align: baseline;"> methods that return information about the world outside the code under test and don't modify anything, e.g., </span></span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">getUser()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;">, </span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">findResults()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;">, </span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">readFile()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;">.</span></span></span></span></li> </ul> <div> <span id="docs-internal-guid-b50ac775-4769-cfca-bf47-888737e7a7a6" style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">You should usually</span><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">avoid verifying that non-state-changing methods are called</span><span style="vertical-align: baseline; white-space: pre-wrap;">:</span></span></div> <div> <ul> <li><span style="white-space: pre-wrap;"><span id="docs-internal-guid-b50ac775-476a-0b38-ad94-1b29a85f5efa" style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; vertical-align: baseline;">It is often redundant</span><span style="vertical-align: baseline;">: </span><span style="color: purple; font-weight: 700; vertical-align: baseline;">a method call that doesn't change the state of the world is meaningless on its own</span><span style="vertical-align: baseline;">. The code under test will use the return value of the method call to do other work that you can assert.</span></span></span></li> <li><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-b50ac775-476a-3f9e-a716-d10db0b69539"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; vertical-align: baseline;">It makes tests brittle</span><span style="vertical-align: baseline;">: tests need to be updated whenever method calls change. For example, if a test is expecting </span></span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">mockUserService.isUserActive(USER)</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;"><span style="font-family: "times" , "times new roman" , serif;"> to be called, it would fail if the code under test is modified to call</span> </span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">user.isActive()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;"> instead.</span></span></span></span></li> <li><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-b50ac775-476a-600b-2bc2-7097a5926df1" style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; vertical-align: baseline;">It makes tests less readable</span><span style="vertical-align: baseline;">: the additional assertions in the test make it more difficult to determine which method calls actually affect the state of the world.</span></span></span></span></span></li> <li><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span style="vertical-align: baseline;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-b50ac775-476a-88c9-7600-1e4248cd477e" style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; vertical-align: baseline;">It gives a false sense of security</span><span style="vertical-align: baseline;">: just because the code under test called a method does not mean the code under test did the right thing with the method’s return value.</span></span></span></span></span></span></li> </ul> </div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: transparent; color: black; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Instead of verifying that they are called,</span><span style="background-color: transparent; color: #980000; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: purple; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">use non-state-changing methods to simulate different conditions in tests</span><span style="background-color: transparent; color: black; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">, e.g., </span></span><span style="background-color: transparent; color: #00931e; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "courier new" , "courier" , monospace;">when(mockUserService.isUserActive(USER)).thenReturn(false)</span></span><span style="background-color: transparent; color: black; font-family: "times" , "times new roman" , serif; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. Then write assertions for the return value of the code under test, or verify state-changing method calls.</span></div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"> <span style="background-color: transparent; color: black; font-family: "times" , "times new roman" , serif; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Verifying non-state-changing method calls may be useful if there is no other output you can assert. For example, if your code should be caching an RPC result, you can verify that the method that makes the RPC is called only once.</span></div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"> <span id="docs-internal-guid-b50ac775-476b-bcdb-84c9-11891429fe3d" style="font-family: "times" , "times new roman" , serif;"><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">With the unnecessary verifications removed, the test looks like this</span><span style="vertical-align: baseline; white-space: pre-wrap;">:</span></span></div> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #fff2cc; vertical-align: top; width: 607px;"><pre style="background-color: #fff2cc; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;">@Test public void addPermissionToDatabase() { new UserAuthorizer(<span style="font-weight: bold;">mockUserService</span>, <span style="font-weight: bold;">mockPermissionDb</span>).grantPermission(USER, READ_ACCESS); </span></pre> <pre style="background-color: #fff2cc; border: 0px; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;"> </span></pre> <pre style="background-color: #fff2cc; border: 0px; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="color: black; font-family: "consolas" , "courier new" , "courier" , monospace;"> <span style="color: blue;">// Verify only the state-changing method.</span> verify(<span style="font-weight: bold;">mockPermissionDb</span>).addPermission(USER, READ_ACCESS); } </span></pre> </td></tr> </tbody></table> </div> <br /> <span id="docs-internal-guid-b50ac775-476f-418d-5b05-5a504162abb7"></span><br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"> <span id="docs-internal-guid-b50ac775-476f-418d-5b05-5a504162abb7"><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">That’s much simpler! But remember that instead of using a mock to verify that a method was called, </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">it would be even better to use a real or</span></span><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><a href="https://testing.googleblog.com/2013/06/testing-on-toilet-fake-your-way-to.html" style="text-decoration-line: none;"><span style="color: #1155cc; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">fake object</span></a><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="vertical-align: baseline; white-space: pre-wrap;">to actually execute the method and check that it works properly. For example, the above test could use a fake database to check that the permission exists in the database rather than just verifying that </span></span><span style="color: #00931e; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "courier new" , "courier" , monospace;">addPermission()</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"> was called.</span><span style="font-family: "times" , "times new roman" , serif;"> </span></span></span><br /> <span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span> <span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: Times, Times New Roman, serif;"><span style="font-style: italic; vertical-align: baseline;">You can learn more about this topic in the book </span><a class="m_5763211666182523148m_-1367602418583969106cremed m_5763211666182523148cremed" data-saferedirecturl="https://www.google.com/url?hl=en&q=http://www.growing-object-oriented-software.com/&source=gmail&ust=1513118358215000&usg=AFQjCNGL6EuV0T86ZLsLyUi4VcPIa8fIVQ" href="http://www.growing-object-oriented-software.com/" style="background-color: white; color: #1155cc; text-decoration-line: none; white-space: normal;" target="_blank"><span style="background-color: transparent; font-style: italic; text-decoration-line: underline; vertical-align: baseline; white-space: pre-wrap;">Growing Object-Oriented Software, Guided by Tests</span></a><span style="font-style: italic; vertical-align: baseline;">. Note that the book uses the terms “command” and “query” instead of “state-changing” and “non-state-changing”.</span></span></span></div> <span id="docs-internal-guid-b50ac775-476f-418d-5b05-5a504162abb7"> </span> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <i><span style="font-family: "times" , "times new roman" , serif;">This article was adapted from a <a href="http://googletesting.blogspot.com/2007/01/introducing-testing-on-toilet.html">Google Testing on the Toilet</a> (TotT) episode. You can download a <a href="https://docs.google.com/document/d/1A0USfjPsmS4fSpgCfunBab8azRIPDTIKi-wRZD1K58k/edit?usp=sharing" rel="nofollow">printer-friendly version</a> of this TotT episode and post it in your office.</span></i><br /> <i><br /></i><span style="font-family: "times" , "times new roman" , serif;"> By Dillon Bly and Andrew Trenk</span><br /> <span style="font-family: "times" , "times new roman" , serif;"><br /></span> <span style="font-family: "times" , "times new roman" , serif;">Which lines can be safely removed from this test?</span><br /> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #f4cccc; vertical-align: top; width: 607px;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;">@Test public void addPermissionToDatabase() { new UserAuthorizer(<span style="font-weight: bold;">mockUserService</span>, <span style="font-weight: bold;">mockPermissionDb</span>).grantPermission(USER, READ_ACCESS); </span></pre> <pre style="background-color: #f4cccc; border: 0px; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;"> </span></pre> <pre style="background-color: #f4cccc; border: 0px; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="color: black; font-family: "consolas" , "courier new" , "courier" , monospace;"> <span style="color: blue;">// The test will fail if any of these methods is not called.</span> verify(<span style="font-weight: bold;">mockUserService</span>).isUserActive(USER); verify(<span style="font-weight: bold;">mockPermissionDb</span>).getPermissions(USER); verify(<span style="font-weight: bold;">mockPermissionDb</span>).isValidPermission(READ_ACCESS); verify(<span style="font-weight: bold;">mockPermissionDb</span>).addPermission(USER, READ_ACCESS); }</span></pre> </td></tr> </tbody></table> </div> <span style="font-size: 12pt; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span id="docs-internal-guid-b50ac775-4768-13da-eaac-0ee595ad284f" style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">The answer is that </span><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">the calls to verify the non-state-changing methods can be removed</span><span style="vertical-align: baseline; white-space: pre-wrap;">.</span></span><br /> <span style="font-size: 12pt; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span id="docs-internal-guid-b50ac775-4768-4d70-7394-a597c452b64e" style="font-family: "times" , "times new roman" , serif;"><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Method calls on another object fall into one of two categories</span><span style="vertical-align: baseline; white-space: pre-wrap;">:</span></span><br /> <ul> <li><span style="white-space: pre-wrap;"><span id="docs-internal-guid-b50ac775-4768-8635-e00b-dd78588a4f61"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; font-weight: 700; vertical-align: baseline;">State-changing</span><span style="vertical-align: baseline;">: methods that have side effects and change the world outside the code under test, </span></span><span style="vertical-align: baseline;"><span style="font-family: "times" , "times new roman" , serif;">e.g.,</span> </span></span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">sendEmail()</span></span><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline;">,</span><span style="vertical-align: baseline;"> </span></span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">saveRecord()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;">, </span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">logAccess()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;">.</span></span></span></li> <li><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-b50ac775-4768-c934-c2fa-bd06b2961ff3"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; font-weight: 700; vertical-align: baseline;">Non-state-changing</span><span style="font-style: italic; vertical-align: baseline;">:</span><span style="vertical-align: baseline;"> methods that return information about the world outside the code under test and don't modify anything, e.g., </span></span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">getUser()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;">, </span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">findResults()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;">, </span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">readFile()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;">.</span></span></span></span></li> </ul> <div> <span id="docs-internal-guid-b50ac775-4769-cfca-bf47-888737e7a7a6" style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">You should usually</span><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">avoid verifying that non-state-changing methods are called</span><span style="vertical-align: baseline; white-space: pre-wrap;">:</span></span></div> <div> <ul> <li><span style="white-space: pre-wrap;"><span id="docs-internal-guid-b50ac775-476a-0b38-ad94-1b29a85f5efa" style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; vertical-align: baseline;">It is often redundant</span><span style="vertical-align: baseline;">: </span><span style="color: purple; font-weight: 700; vertical-align: baseline;">a method call that doesn't change the state of the world is meaningless on its own</span><span style="vertical-align: baseline;">. The code under test will use the return value of the method call to do other work that you can assert.</span></span></span></li> <li><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-b50ac775-476a-3f9e-a716-d10db0b69539"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; vertical-align: baseline;">It makes tests brittle</span><span style="vertical-align: baseline;">: tests need to be updated whenever method calls change. For example, if a test is expecting </span></span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">mockUserService.isUserActive(USER)</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;"><span style="font-family: "times" , "times new roman" , serif;"> to be called, it would fail if the code under test is modified to call</span> </span><span style="color: #00931e; vertical-align: baseline;"><span style="font-family: "courier new" , "courier" , monospace;">user.isActive()</span></span><span style="font-family: "times" , "times new roman" , serif; vertical-align: baseline;"> instead.</span></span></span></span></li> <li><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-b50ac775-476a-600b-2bc2-7097a5926df1" style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; vertical-align: baseline;">It makes tests less readable</span><span style="vertical-align: baseline;">: the additional assertions in the test make it more difficult to determine which method calls actually affect the state of the world.</span></span></span></span></span></li> <li><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span style="vertical-align: baseline;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-b50ac775-476a-88c9-7600-1e4248cd477e" style="font-family: "times" , "times new roman" , serif;"><span style="font-style: italic; vertical-align: baseline;">It gives a false sense of security</span><span style="vertical-align: baseline;">: just because the code under test called a method does not mean the code under test did the right thing with the method’s return value.</span></span></span></span></span></span></li> </ul> </div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: transparent; color: black; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Instead of verifying that they are called,</span><span style="background-color: transparent; color: #980000; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: purple; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">use non-state-changing methods to simulate different conditions in tests</span><span style="background-color: transparent; color: black; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">, e.g., </span></span><span style="background-color: transparent; color: #00931e; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "courier new" , "courier" , monospace;">when(mockUserService.isUserActive(USER)).thenReturn(false)</span></span><span style="background-color: transparent; color: black; font-family: "times" , "times new roman" , serif; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. Then write assertions for the return value of the code under test, or verify state-changing method calls.</span></div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"> <span style="background-color: transparent; color: black; font-family: "times" , "times new roman" , serif; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Verifying non-state-changing method calls may be useful if there is no other output you can assert. For example, if your code should be caching an RPC result, you can verify that the method that makes the RPC is called only once.</span></div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"> <span id="docs-internal-guid-b50ac775-476b-bcdb-84c9-11891429fe3d" style="font-family: "times" , "times new roman" , serif;"><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">With the unnecessary verifications removed, the test looks like this</span><span style="vertical-align: baseline; white-space: pre-wrap;">:</span></span></div> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #fff2cc; vertical-align: top; width: 607px;"><pre style="background-color: #fff2cc; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;">@Test public void addPermissionToDatabase() { new UserAuthorizer(<span style="font-weight: bold;">mockUserService</span>, <span style="font-weight: bold;">mockPermissionDb</span>).grantPermission(USER, READ_ACCESS); </span></pre> <pre style="background-color: #fff2cc; border: 0px; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;"> </span></pre> <pre style="background-color: #fff2cc; border: 0px; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="color: black; font-family: "consolas" , "courier new" , "courier" , monospace;"> <span style="color: blue;">// Verify only the state-changing method.</span> verify(<span style="font-weight: bold;">mockPermissionDb</span>).addPermission(USER, READ_ACCESS); } </span></pre> </td></tr> </tbody></table> </div> <br /> <span id="docs-internal-guid-b50ac775-476f-418d-5b05-5a504162abb7"></span><br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"> <span id="docs-internal-guid-b50ac775-476f-418d-5b05-5a504162abb7"><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">That’s much simpler! But remember that instead of using a mock to verify that a method was called, </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">it would be even better to use a real or</span></span><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><a href="https://testing.googleblog.com/2013/06/testing-on-toilet-fake-your-way-to.html" style="text-decoration-line: none;"><span style="color: #1155cc; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">fake object</span></a><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="vertical-align: baseline; white-space: pre-wrap;">to actually execute the method and check that it works properly. For example, the above test could use a fake database to check that the permission exists in the database rather than just verifying that </span></span><span style="color: #00931e; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "courier new" , "courier" , monospace;">addPermission()</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"> was called.</span><span style="font-family: "times" , "times new roman" , serif;"> </span></span></span><br /> <span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span> <span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: Times, Times New Roman, serif;"><span style="font-style: italic; vertical-align: baseline;">You can learn more about this topic in the book </span><a class="m_5763211666182523148m_-1367602418583969106cremed m_5763211666182523148cremed" data-saferedirecturl="https://www.google.com/url?hl=en&q=http://www.growing-object-oriented-software.com/&source=gmail&ust=1513118358215000&usg=AFQjCNGL6EuV0T86ZLsLyUi4VcPIa8fIVQ" href="http://www.growing-object-oriented-software.com/" style="background-color: white; color: #1155cc; text-decoration-line: none; white-space: normal;" target="_blank"><span style="background-color: transparent; font-style: italic; text-decoration-line: underline; vertical-align: baseline; white-space: pre-wrap;">Growing Object-Oriented Software, Guided by Tests</span></a><span style="font-style: italic; vertical-align: baseline;">. Note that the book uses the terms “command” and “query” instead of “state-changing” and “non-state-changing”.</span></span></span></div> <span id="docs-internal-guid-b50ac775-476f-418d-5b05-5a504162abb7"> </span> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </noscript> </div> </div> <div class='share'> <span class='twitter-custom social-wrapper' data-href='http://twitter.com/share?text=Google Testing Blog:Testing on the Toilet: Only Verify State-Changing Method Calls&url=https://testing.googleblog.com/2017/12/testing-on-toilet-only-verify-state.html&via=googletesting'> <img alt='Share on Twitter' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_twitter_black_24dp.png' width='24'/> </span> <span class='fb-custom social-wrapper' data-href='https://www.facebook.com/sharer.php?u=https://testing.googleblog.com/2017/12/testing-on-toilet-only-verify-state.html'> <img alt='Share on Facebook' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_facebook_black_24dp.png' width='24'/> </span> </div> <div class='comment-container'> <i class='comment-img material-icons'>  </i> <a href='https://testing.googleblog.com/2017/12/testing-on-toilet-only-verify-state.html#comments' style='font-weight: 500; text-decoration: underline;'>3 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2017/12/testing-on-toilet-only-verify-state.html' data-viewtype='FILTERED_POSTMOD'></div> <a href='https://plus.google.com/112374322230920073195' rel='author' style='display:none;'> Google </a> <div class='label-footer'> <span class='labels-caption'> Labels: </span> <span class='labels'> <a class='label' href='https://testing.googleblog.com/search/label/Andrew%20Trenk' rel='tag'> Andrew Trenk </a> , <a class='label' href='https://testing.googleblog.com/search/label/Dillon%20Bly' rel='tag'> Dillon Bly </a> , <a class='label' href='https://testing.googleblog.com/search/label/TotT' rel='tag'> TotT </a> </span> </div> </div> </div> <div class='post' data-id='5254716936760689715' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2017/11/obsessed-with-primitives.html' itemprop='url' title='Code Health: Obsessed With Primitives?'> Code Health: Obsessed With Primitives? </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Monday, November 13, 2017 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span id="docs-internal-guid-ea42980b-b759-ef9b-bfd2-6f124227358f"></span><br /> <div 1.38="" dirline-height:="" ltr="" style="margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-ea42980b-b759-ef9b-bfd2-6f124227358f"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1UKXAXxBtMhjw2HcUdubwC8wwo6bl3gYUYmpy_9DXU1c/edit?usp=sharing" rel="nofollow" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> to display in your office. </span></span></span></div> <span id="docs-internal-guid-ea42980b-b759-ef9b-bfd2-6f124227358f"> </span><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;"><br /></span></span> <span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">By Marc Eaddy</span></span><br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;"><br /></span></span> <span id="docs-internal-guid-c44fb159-b735-baf6-4f46-d53e212fba61" style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">Programming languages provide basic types, such as integers, strings, and maps, which are useful in many contexts. For example, a string can be used to hold everything from a person's name to a web page URL. However, </span><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">code that relies too heavily on basic types instead of custom abstractions can be hard to understand and maintain</span><span style="vertical-align: baseline; white-space: pre-wrap;">.</span></span><br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span id="docs-internal-guid-c44fb159-b735-ecce-345e-b204f37629f0"><span style="color: purple;"><span style="font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Primitive obsession</span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> is the overuse of basic ("primitive") types to represent higher-level concepts. </span></span><span style="vertical-align: baseline; white-space: pre-wrap;">For example, this code uses basic types to represent shapes:</span></span></span><br /> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #f4cccc; vertical-align: top; width: 607px;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;">vector<pair<int, int>> polygon = ... pair<pair<int, int>, pair<int, int>> bounding_box = GetBoundingBox(polygon); int area = (bounding_box.second.first - bounding_box.first.first) * (bounding_box.second.second - bounding_box.first.second);</span></pre> </td></tr> </tbody></table> </div> <span id="docs-internal-guid-c44fb159-b73f-79c4-6112-c305b854049e"><code>pair</code><span style="vertical-align: baseline; white-space: pre-wrap;"> <span style="font-family: "times" , "times new roman" , serif;">is not the right level of abstraction because its generically-named </span></span><span style="font-family: "times" , "times new roman" , serif;"><code>first</code><span style="vertical-align: baseline; white-space: pre-wrap;"> and </span><code>second</code><span style="vertical-align: baseline; white-space: pre-wrap;"> fields are used to represent </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">X</span><span style="vertical-align: baseline; white-space: pre-wrap;"> and </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Y</span><span style="vertical-align: baseline; white-space: pre-wrap;"> in one case and </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">lower-left</span><span style="vertical-align: baseline; white-space: pre-wrap;"> (er, </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">upper-left</span><span style="vertical-align: baseline; white-space: pre-wrap;">?) and </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">upper-right</span><span style="vertical-align: baseline; white-space: pre-wrap;"> (er, </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">lower-right</span><span style="vertical-align: baseline; white-space: pre-wrap;">?) in the other. Worse, </span><span style="color: purple;"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">basic types don't encapsulate</span><span style="vertical-align: baseline; white-space: pre-wrap;"> </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">domain-specific code</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"> such as computing the bounding box and area.</span></span></span><br /> <br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;"><span id="docs-internal-guid-c44fb159-b741-ef35-eba2-3bf8a6024e3e"><span style="color: purple; font-family: "times" , "times new roman" , serif; font-weight: 700; vertical-align: baseline;">Replacing basic types with higher-level abstractions results in clearer and better encapsulated code:</span></span></span></span><br /> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #d9ead3; vertical-align: top; width: 607px;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;">Polygon polygon = ... int area = polygon.GetBoundingBox().GetArea();</span></pre> </td></tr> </tbody></table> </div> <div style="overflow-x: auto;"> <span id="docs-internal-guid-c44fb159-b745-02ec-a269-ec156b175826"><span style="color: purple;"><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Here are some other examples of primitive obsession</span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;">:</span></span></span></div> <div style="overflow-x: auto;"> <ul> <li><span style="color: purple;"><span style="white-space: pre-wrap;"><span id="docs-internal-guid-c44fb159-b74a-5986-e629-db1c2dc73c49"><span style="color: black; font-family: "times" , "times new roman" , serif; vertical-align: baseline;">Related maps, lists, vectors, etc. that can be easily combined into a single collection by consolidating the values into a custom higher-level abstraction.</span></span></span></span> <table class="my-bordered-table"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">map<UserId, string> id_to_name; map<UserId, int> id_to_age;</pre> </td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">map<UserId, Person> id_to_person;</pre> </td> </tr> </tbody></table> </li> <li dir="ltr" style="list-style-type: disc; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 5pt;"> <span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">A v</span><span style="vertical-align: baseline; white-space: pre-wrap;">ector or map with magic indices/keys, e.g. string values at indices/keys </span><span style="vertical-align: baseline; white-space: pre-wrap;">0</span><span style="vertical-align: baseline; white-space: pre-wrap;">, </span><span style="vertical-align: baseline; white-space: pre-wrap;">1</span><span style="vertical-align: baseline; white-space: pre-wrap;">, and </span><span style="vertical-align: baseline; white-space: pre-wrap;">2</span><span style="vertical-align: baseline; white-space: pre-wrap;"> hold </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">name</span><span style="vertical-align: baseline; white-space: pre-wrap;">, </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">address</span><span style="vertical-align: baseline; white-space: pre-wrap;">, and </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">phone #</span><span style="vertical-align: baseline; white-space: pre-wrap;">, respectively. Instead, consolidate these values into a higher-level abstraction.</span></span></div> <table class="my-bordered-table" style="font-size: 13pt;"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;"><span style="font-size: small;">person_data[kName] = "Foo";</span></pre> </td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;"><span style="font-size: small;">person.SetName("Foo");</span></pre> </td> </tr> </tbody></table> </li> <li><span style="color: purple;"><span style="white-space: pre-wrap;"><span id="docs-internal-guid-c44fb159-b74a-5986-e629-db1c2dc73c49"><span style="color: black; font-family: "times" , "times new roman" , serif; vertical-align: baseline;">A string that holds complex or structured text (e.g. a date). Instead, use a higher-level abstraction (e.g. <code>Date</code>) that provides self-documenting accessors (e.g. <code>GetMonth</code> ) and guarantees correctness.</span></span></span></span> <table class="my-bordered-table"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">string date = "01-02-03";</pre> </td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">Date date(Month::Feb, Day(1), Year(2003));</pre> </td> </tr> </tbody></table> </li> <li><span style="color: purple;"><span style="white-space: pre-wrap;"><span id="docs-internal-guid-c44fb159-b74a-5986-e629-db1c2dc73c49"><span style="color: black; font-family: "times" , "times new roman" , serif; vertical-align: baseline;">An integer or floating point number that stores a time value, e.g. seconds. Instead, use a structured timestamp or duration type.</span></span></span></span> <table class="my-bordered-table"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">int timeout_secs = 5;</pre> </td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">Duration timeout = Seconds(5);</pre> </td> </tr> </tbody></table> </li> </ul> </div> <span id="docs-internal-guid-c44fb159-b757-da30-9a3a-ac31c0c278f9"><span style="font-family: "times" , "times new roman" , serif;"><span style="color: purple;"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">It's possible for any type—from a lowly </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> to a sophisticated red-black tree—to be too primitive for the job.</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"> If you see code that uses a lot of basic types that would be clearer or better encapsulated by using a higher-level abstraction, refactor it or politely remind the author to </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">keep it classy</span><span style="vertical-align: baseline; white-space: pre-wrap;">!</span></span></span> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <span id="docs-internal-guid-ea42980b-b759-ef9b-bfd2-6f124227358f"></span><br /> <div 1.38="" dirline-height:="" ltr="" style="margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-ea42980b-b759-ef9b-bfd2-6f124227358f"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1UKXAXxBtMhjw2HcUdubwC8wwo6bl3gYUYmpy_9DXU1c/edit?usp=sharing" rel="nofollow" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> to display in your office. </span></span></span></div> <span id="docs-internal-guid-ea42980b-b759-ef9b-bfd2-6f124227358f"> </span><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;"><br /></span></span> <span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">By Marc Eaddy</span></span><br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;"><br /></span></span> <span id="docs-internal-guid-c44fb159-b735-baf6-4f46-d53e212fba61" style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">Programming languages provide basic types, such as integers, strings, and maps, which are useful in many contexts. For example, a string can be used to hold everything from a person's name to a web page URL. However, </span><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">code that relies too heavily on basic types instead of custom abstractions can be hard to understand and maintain</span><span style="vertical-align: baseline; white-space: pre-wrap;">.</span></span><br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span id="docs-internal-guid-c44fb159-b735-ecce-345e-b204f37629f0"><span style="color: purple;"><span style="font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Primitive obsession</span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> is the overuse of basic ("primitive") types to represent higher-level concepts. </span></span><span style="vertical-align: baseline; white-space: pre-wrap;">For example, this code uses basic types to represent shapes:</span></span></span><br /> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #f4cccc; vertical-align: top; width: 607px;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;">vector<pair<int, int>> polygon = ... pair<pair<int, int>, pair<int, int>> bounding_box = GetBoundingBox(polygon); int area = (bounding_box.second.first - bounding_box.first.first) * (bounding_box.second.second - bounding_box.first.second);</span></pre> </td></tr> </tbody></table> </div> <span id="docs-internal-guid-c44fb159-b73f-79c4-6112-c305b854049e"><code>pair</code><span style="vertical-align: baseline; white-space: pre-wrap;"> <span style="font-family: "times" , "times new roman" , serif;">is not the right level of abstraction because its generically-named </span></span><span style="font-family: "times" , "times new roman" , serif;"><code>first</code><span style="vertical-align: baseline; white-space: pre-wrap;"> and </span><code>second</code><span style="vertical-align: baseline; white-space: pre-wrap;"> fields are used to represent </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">X</span><span style="vertical-align: baseline; white-space: pre-wrap;"> and </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Y</span><span style="vertical-align: baseline; white-space: pre-wrap;"> in one case and </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">lower-left</span><span style="vertical-align: baseline; white-space: pre-wrap;"> (er, </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">upper-left</span><span style="vertical-align: baseline; white-space: pre-wrap;">?) and </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">upper-right</span><span style="vertical-align: baseline; white-space: pre-wrap;"> (er, </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">lower-right</span><span style="vertical-align: baseline; white-space: pre-wrap;">?) in the other. Worse, </span><span style="color: purple;"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">basic types don't encapsulate</span><span style="vertical-align: baseline; white-space: pre-wrap;"> </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">domain-specific code</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"> such as computing the bounding box and area.</span></span></span><br /> <br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;"><span id="docs-internal-guid-c44fb159-b741-ef35-eba2-3bf8a6024e3e"><span style="color: purple; font-family: "times" , "times new roman" , serif; font-weight: 700; vertical-align: baseline;">Replacing basic types with higher-level abstractions results in clearer and better encapsulated code:</span></span></span></span><br /> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #d9ead3; vertical-align: top; width: 607px;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;">Polygon polygon = ... int area = polygon.GetBoundingBox().GetArea();</span></pre> </td></tr> </tbody></table> </div> <div style="overflow-x: auto;"> <span id="docs-internal-guid-c44fb159-b745-02ec-a269-ec156b175826"><span style="color: purple;"><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Here are some other examples of primitive obsession</span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;">:</span></span></span></div> <div style="overflow-x: auto;"> <ul> <li><span style="color: purple;"><span style="white-space: pre-wrap;"><span id="docs-internal-guid-c44fb159-b74a-5986-e629-db1c2dc73c49"><span style="color: black; font-family: "times" , "times new roman" , serif; vertical-align: baseline;">Related maps, lists, vectors, etc. that can be easily combined into a single collection by consolidating the values into a custom higher-level abstraction.</span></span></span></span> <table class="my-bordered-table"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">map<UserId, string> id_to_name; map<UserId, int> id_to_age;</pre> </td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">map<UserId, Person> id_to_person;</pre> </td> </tr> </tbody></table> </li> <li dir="ltr" style="list-style-type: disc; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 5pt;"> <span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">A v</span><span style="vertical-align: baseline; white-space: pre-wrap;">ector or map with magic indices/keys, e.g. string values at indices/keys </span><span style="vertical-align: baseline; white-space: pre-wrap;">0</span><span style="vertical-align: baseline; white-space: pre-wrap;">, </span><span style="vertical-align: baseline; white-space: pre-wrap;">1</span><span style="vertical-align: baseline; white-space: pre-wrap;">, and </span><span style="vertical-align: baseline; white-space: pre-wrap;">2</span><span style="vertical-align: baseline; white-space: pre-wrap;"> hold </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">name</span><span style="vertical-align: baseline; white-space: pre-wrap;">, </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">address</span><span style="vertical-align: baseline; white-space: pre-wrap;">, and </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">phone #</span><span style="vertical-align: baseline; white-space: pre-wrap;">, respectively. Instead, consolidate these values into a higher-level abstraction.</span></span></div> <table class="my-bordered-table" style="font-size: 13pt;"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;"><span style="font-size: small;">person_data[kName] = "Foo";</span></pre> </td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;"><span style="font-size: small;">person.SetName("Foo");</span></pre> </td> </tr> </tbody></table> </li> <li><span style="color: purple;"><span style="white-space: pre-wrap;"><span id="docs-internal-guid-c44fb159-b74a-5986-e629-db1c2dc73c49"><span style="color: black; font-family: "times" , "times new roman" , serif; vertical-align: baseline;">A string that holds complex or structured text (e.g. a date). Instead, use a higher-level abstraction (e.g. <code>Date</code>) that provides self-documenting accessors (e.g. <code>GetMonth</code> ) and guarantees correctness.</span></span></span></span> <table class="my-bordered-table"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">string date = "01-02-03";</pre> </td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">Date date(Month::Feb, Day(1), Year(2003));</pre> </td> </tr> </tbody></table> </li> <li><span style="color: purple;"><span style="white-space: pre-wrap;"><span id="docs-internal-guid-c44fb159-b74a-5986-e629-db1c2dc73c49"><span style="color: black; font-family: "times" , "times new roman" , serif; vertical-align: baseline;">An integer or floating point number that stores a time value, e.g. seconds. Instead, use a structured timestamp or duration type.</span></span></span></span> <table class="my-bordered-table"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">int timeout_secs = 5;</pre> </td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-top: 0;">Duration timeout = Seconds(5);</pre> </td> </tr> </tbody></table> </li> </ul> </div> <span id="docs-internal-guid-c44fb159-b757-da30-9a3a-ac31c0c278f9"><span style="font-family: "times" , "times new roman" , serif;"><span style="color: purple;"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">It's possible for any type—from a lowly </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> to a sophisticated red-black tree—to be too primitive for the job.</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"> If you see code that uses a lot of basic types that would be clearer or better encapsulated by using a higher-level abstraction, refactor it or politely remind the author to </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">keep it classy</span><span style="vertical-align: baseline; white-space: pre-wrap;">!</span></span></span> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </noscript> </div> </div> <div class='share'> <span class='twitter-custom social-wrapper' data-href='http://twitter.com/share?text=Google Testing Blog:Code Health: Obsessed With Primitives?&url=https://testing.googleblog.com/2017/11/obsessed-with-primitives.html&via=googletesting'> <img alt='Share on Twitter' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_twitter_black_24dp.png' width='24'/> </span> <span class='fb-custom social-wrapper' data-href='https://www.facebook.com/sharer.php?u=https://testing.googleblog.com/2017/11/obsessed-with-primitives.html'> <img alt='Share on Facebook' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_facebook_black_24dp.png' width='24'/> </span> </div> <div class='comment-container'> <i class='comment-img material-icons'>  </i> <a href='https://testing.googleblog.com/2017/11/obsessed-with-primitives.html#comments' style='font-weight: 500; text-decoration: underline;'>3 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2017/11/obsessed-with-primitives.html' data-viewtype='FILTERED_POSTMOD'></div> <a href='https://plus.google.com/112374322230920073195' rel='author' style='display:none;'> Google </a> <div class='label-footer'> <span class='labels-caption'> Labels: </span> <span class='labels'> <a class='label' href='https://testing.googleblog.com/search/label/Code%20Health' rel='tag'> Code Health </a> , <a class='label' href='https://testing.googleblog.com/search/label/Marc%20Eaddy' rel='tag'> Marc Eaddy </a> , <a class='label' href='https://testing.googleblog.com/search/label/TotT' rel='tag'> TotT </a> </span> </div> </div> </div> <div class='post' data-id='4297826725077210649' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html' itemprop='url' title='Code Health: IdentifierNamingPostForWorldWideWebBlog'> Code Health: IdentifierNamingPostForWorldWideWebBlog </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Monday, October 23, 2017 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span id="docs-internal-guid-cafa72a5-4a59-b8e6-8bc9-61e13fa3722c"></span><br /> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; font-style: italic; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration: none;"><span style="background-color: white; color: #1155cc; font-style: italic; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; font-style: italic; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration: none;"><span style="background-color: white; color: #1155cc; font-style: italic; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; font-style: italic; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1pwxIjkmwwGjpCF9CjeWxMoNtqAs0aXLkwfen5MTTPAs/edit?usp=sharing" rel="nofollow" style="text-decoration: none;"><span style="background-color: white; color: #1155cc; font-style: italic; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; font-style: italic; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> to display in your office.</span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; color: #222222; font-size: 9.5pt; font-style: italic; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; color: #222222; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">By Chris Lewis and Bob Nystrom</span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; color: #222222; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span> <span style="background-color: white; color: #222222; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span id="docs-internal-guid-107ab32d-4a5d-b217-ea3f-518223b2293f"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: transparent; color: black; vertical-align: baseline;">It's easy to get carried away creating long identifiers. Longer names often make things more readable. But </span><span style="color: purple;"><span style="background-color: transparent; font-weight: 700; vertical-align: baseline;">names that are </span><span style="background-color: transparent; font-style: italic; font-weight: 700; vertical-align: baseline;">too</span><span style="background-color: transparent; font-weight: 700; vertical-align: baseline;"> long can decrease readability</span></span><span style="background-color: transparent; color: black; vertical-align: baseline;">. There are many examples of variable names longer than 60 characters on GitHub and elsewhere. </span><span style="background-color: transparent; font-weight: 700; vertical-align: baseline;"><span style="color: purple;">In 58 characters, we managed this haiku for you to consider</span></span><span style="background-color: transparent; color: black; vertical-align: baseline;">:</span></span></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: transparent; color: black; font-family: "times" , "times new roman" , serif; vertical-align: baseline;"><br /></span></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span id="docs-internal-guid-107ab32d-4a5e-c1c8-9045-dfd0291b6579"><span style="background-color: transparent; font-weight: 700; vertical-align: baseline;"><span style="font-family: "times" , "times new roman" , serif;"> Name variables</span></span></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="background-color: transparent; font-weight: 700; vertical-align: baseline;"> </span></span><span style="font-weight: 700; white-space: pre-wrap;">Using these simple guidelines</span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-107ab32d-4a5f-75e6-777b-788c846457f5"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"> Beautiful source code</span></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-107ab32d-4a60-29a8-7d06-c834e5155cdf" style="font-family: "times" , "times new roman" , serif;"><span style="color: purple;"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Names should be two things: </span><span style="font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">clear</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"> (know what it refers to) </span><span style="color: purple;"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">and </span><span style="font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">precise</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"> (know what it does </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">not</span><span style="vertical-align: baseline; white-space: pre-wrap;"> refer to). Here are some guidelines to help:</span></span></div> <div style="overflow-x: auto;"> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"></span><br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"><span style="color: purple; font-family: "times" , "times new roman" , serif; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">• Omit words that are obvious given a variable's type declaratio</span><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: Times, Times New Roman, serif;">n</span><span style="font-size: 13pt;">.</span></span></span></div> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"> </span></div> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #cfe2f3; vertical-align: top; width: 607px;"><pre style="background-color: #cfe2f3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;"><span style="color: #00931e;">// Bad, the type tells us what these variables are:</span> String nameString; List<datetime> holidayDateList; <span style="color: #00931e;">// Better:</span> String name; List<datetime> holidays; </span></pre> </td></tr> </tbody></table> </div> <div style="overflow-x: auto;"> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"></span><br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"><span style="color: purple; font-family: "times" , "times new roman" , serif; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">• Omit irrelevant details.</span></span></div> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"> </span></div> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #cfe2f3; vertical-align: top; width: 607px;"><pre style="background-color: #cfe2f3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;"><span style="color: #00931e;">// Overly specific names are hard to read:</span> Monster finalBattleMostDangerousBossMonster; Payments nonTypicalMonthlyPayments; <span style="color: #00931e;">// Better, if there's no other monsters or payments that need disambiguation:</span> Monster boss; Payments payments; </span></pre> </td></tr> </tbody></table> </div> <div style="overflow-x: auto;"> <span style="font-family: "times" , "times new roman" , serif;"><span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"></span><br /></span> <br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"><span style="color: purple; font-family: "times" , "times new roman" , serif; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">• Omit words that are clear from the surrounding context.</span></span></div> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"> </span></div> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #cfe2f3; vertical-align: top; width: 607px;"><pre style="background-color: #cfe2f3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;"><span style="color: #00931e;">// Bad, repeating the context:</span> class AnnualHolidaySale {int annualSaleRebate; boolean promoteHolidaySale() {...}} <span style="color: #00931e;">// Better:</span> class AnnualHolidaySale {int rebate; boolean promote() {...}} </span></pre> </td></tr> </tbody></table> </div> <br /> <span id="docs-internal-guid-107ab32d-4a72-1f2c-217f-34eb00a5a5d3"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple; font-family: "times" , "times new roman" , serif;">• Omit words that could apply to any identifier.</span></span></span><br /> <span id="docs-internal-guid-107ab32d-4a72-4434-5b67-96f14ca43791"><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">You know the usual suspects: </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">data, state, amount, number, value, manager, engine, object, entity, instance, helper, util, broker, metadata, process, handle, context</span><span style="vertical-align: baseline; white-space: pre-wrap;">. Cut them out.</span></span></span><br /> <span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span id="docs-internal-guid-107ab32d-4a72-82c2-04ea-1fec73b2284c"><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">There are some exceptions to these rules; use your judgment. Names that are too long are still better than names that are too short. However, </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">following these guidelines, your code will remain unambiguous and be much easier to read</span></span><span style="vertical-align: baseline; white-space: pre-wrap;">. Readers, including "future you,” will appreciate how clear your code is!</span></span></span> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <span id="docs-internal-guid-cafa72a5-4a59-b8e6-8bc9-61e13fa3722c"></span><br /> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; font-style: italic; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration: none;"><span style="background-color: white; color: #1155cc; font-style: italic; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; font-style: italic; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration: none;"><span style="background-color: white; color: #1155cc; font-style: italic; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; font-style: italic; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1pwxIjkmwwGjpCF9CjeWxMoNtqAs0aXLkwfen5MTTPAs/edit?usp=sharing" rel="nofollow" style="text-decoration: none;"><span style="background-color: white; color: #1155cc; font-style: italic; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; font-style: italic; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> to display in your office.</span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; color: #222222; font-size: 9.5pt; font-style: italic; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; color: #222222; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">By Chris Lewis and Bob Nystrom</span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; color: #222222; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span> <span style="background-color: white; color: #222222; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span id="docs-internal-guid-107ab32d-4a5d-b217-ea3f-518223b2293f"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: transparent; color: black; vertical-align: baseline;">It's easy to get carried away creating long identifiers. Longer names often make things more readable. But </span><span style="color: purple;"><span style="background-color: transparent; font-weight: 700; vertical-align: baseline;">names that are </span><span style="background-color: transparent; font-style: italic; font-weight: 700; vertical-align: baseline;">too</span><span style="background-color: transparent; font-weight: 700; vertical-align: baseline;"> long can decrease readability</span></span><span style="background-color: transparent; color: black; vertical-align: baseline;">. There are many examples of variable names longer than 60 characters on GitHub and elsewhere. </span><span style="background-color: transparent; font-weight: 700; vertical-align: baseline;"><span style="color: purple;">In 58 characters, we managed this haiku for you to consider</span></span><span style="background-color: transparent; color: black; vertical-align: baseline;">:</span></span></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: transparent; color: black; font-family: "times" , "times new roman" , serif; vertical-align: baseline;"><br /></span></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span id="docs-internal-guid-107ab32d-4a5e-c1c8-9045-dfd0291b6579"><span style="background-color: transparent; font-weight: 700; vertical-align: baseline;"><span style="font-family: "times" , "times new roman" , serif;"> Name variables</span></span></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="background-color: transparent; font-weight: 700; vertical-align: baseline;"> </span></span><span style="font-weight: 700; white-space: pre-wrap;">Using these simple guidelines</span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-107ab32d-4a5f-75e6-777b-788c846457f5"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"> Beautiful source code</span></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-107ab32d-4a60-29a8-7d06-c834e5155cdf" style="font-family: "times" , "times new roman" , serif;"><span style="color: purple;"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Names should be two things: </span><span style="font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">clear</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"> (know what it refers to) </span><span style="color: purple;"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">and </span><span style="font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">precise</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"> (know what it does </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">not</span><span style="vertical-align: baseline; white-space: pre-wrap;"> refer to). Here are some guidelines to help:</span></span></div> <div style="overflow-x: auto;"> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"></span><br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"><span style="color: purple; font-family: "times" , "times new roman" , serif; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">• Omit words that are obvious given a variable's type declaratio</span><span style="color: purple; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: Times, Times New Roman, serif;">n</span><span style="font-size: 13pt;">.</span></span></span></div> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"> </span></div> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #cfe2f3; vertical-align: top; width: 607px;"><pre style="background-color: #cfe2f3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;"><span style="color: #00931e;">// Bad, the type tells us what these variables are:</span> String nameString; List<datetime> holidayDateList; <span style="color: #00931e;">// Better:</span> String name; List<datetime> holidays; </span></pre> </td></tr> </tbody></table> </div> <div style="overflow-x: auto;"> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"></span><br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"><span style="color: purple; font-family: "times" , "times new roman" , serif; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">• Omit irrelevant details.</span></span></div> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"> </span></div> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #cfe2f3; vertical-align: top; width: 607px;"><pre style="background-color: #cfe2f3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;"><span style="color: #00931e;">// Overly specific names are hard to read:</span> Monster finalBattleMostDangerousBossMonster; Payments nonTypicalMonthlyPayments; <span style="color: #00931e;">// Better, if there's no other monsters or payments that need disambiguation:</span> Monster boss; Payments payments; </span></pre> </td></tr> </tbody></table> </div> <div style="overflow-x: auto;"> <span style="font-family: "times" , "times new roman" , serif;"><span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"></span><br /></span> <br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"><span style="color: purple; font-family: "times" , "times new roman" , serif; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">• Omit words that are clear from the surrounding context.</span></span></div> <span id="docs-internal-guid-107ab32d-4a69-9b94-a90a-c8712b9c74c9"> </span></div> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #cfe2f3; vertical-align: top; width: 607px;"><pre style="background-color: #cfe2f3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "consolas" , "courier new" , "courier" , monospace;"><span style="color: #00931e;">// Bad, repeating the context:</span> class AnnualHolidaySale {int annualSaleRebate; boolean promoteHolidaySale() {...}} <span style="color: #00931e;">// Better:</span> class AnnualHolidaySale {int rebate; boolean promote() {...}} </span></pre> </td></tr> </tbody></table> </div> <br /> <span id="docs-internal-guid-107ab32d-4a72-1f2c-217f-34eb00a5a5d3"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple; font-family: "times" , "times new roman" , serif;">• Omit words that could apply to any identifier.</span></span></span><br /> <span id="docs-internal-guid-107ab32d-4a72-4434-5b67-96f14ca43791"><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">You know the usual suspects: </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">data, state, amount, number, value, manager, engine, object, entity, instance, helper, util, broker, metadata, process, handle, context</span><span style="vertical-align: baseline; white-space: pre-wrap;">. Cut them out.</span></span></span><br /> <span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span id="docs-internal-guid-107ab32d-4a72-82c2-04ea-1fec73b2284c"><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">There are some exceptions to these rules; use your judgment. Names that are too long are still better than names that are too short. However, </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">following these guidelines, your code will remain unambiguous and be much easier to read</span></span><span style="vertical-align: baseline; white-space: pre-wrap;">. Readers, including "future you,” will appreciate how clear your code is!</span></span></span> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </noscript> </div> </div> <div class='share'> <span class='twitter-custom social-wrapper' data-href='http://twitter.com/share?text=Google Testing Blog:Code Health: IdentifierNamingPostForWorldWideWebBlog&url=https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html&via=googletesting'> <img alt='Share on Twitter' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_twitter_black_24dp.png' width='24'/> </span> <span class='fb-custom social-wrapper' data-href='https://www.facebook.com/sharer.php?u=https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html'> <img alt='Share on Facebook' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_facebook_black_24dp.png' width='24'/> </span> </div> <div class='comment-container'> <i class='comment-img material-icons'>  </i> <a href='https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html#comments' style='font-weight: 500; text-decoration: underline;'>6 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html' data-viewtype='FILTERED_POSTMOD'></div> <a href='https://plus.google.com/112374322230920073195' rel='author' style='display:none;'> Google </a> <div class='label-footer'> <span class='labels-caption'> Labels: </span> <span class='labels'> <a class='label' href='https://testing.googleblog.com/search/label/Bob%20Nystrom' rel='tag'> Bob Nystrom </a> , <a class='label' href='https://testing.googleblog.com/search/label/Chris%20Lewis' rel='tag'> Chris Lewis </a> , <a class='label' href='https://testing.googleblog.com/search/label/Code%20Health' rel='tag'> Code Health </a> , <a class='label' href='https://testing.googleblog.com/search/label/TotT' rel='tag'> TotT </a> </span> </div> </div> </div> <div class='post' data-id='8046216467923860328' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2017/09/code-health-providing-context-with.html' itemprop='url' title='Code Health: Providing Context with Commit Messages and Bug Reports'> Code Health: Providing Context with Commit Messages and Bug Reports </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Monday, September 11, 2017 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span id="docs-internal-guid-96cdc92b-72a3-298c-9f87-daaddf19a3ec"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1Ub4xrBA6cyJjJ2bgFL7_VynlvJf423p7UBKIWBRMsnU/edit?usp=sharing" rel="nofollow" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> to display in your office.</span></span></span><br /> <span style="background-color: white; color: #222222; font-family: "arial"; font-size: 9.5pt; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">By Chris Lewis</span></span><br /> <span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span> <span id="docs-internal-guid-7555d281-72b2-27f4-085f-2b65456fdd8c"><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">You are caught in a trap. Mechanisms whirl around you, but they make no sense. You desperately search the room and find the builder's original plans! The description of the work order that implemented the trap reads, </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">"Miscellaneous fixes." </span><span style="vertical-align: baseline; white-space: pre-wrap;">Oh dear.</span></span></span><br /> <span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span> <span id="docs-internal-guid-7555d281-72b5-7098-346a-238d0acb67ad"><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">Reading other engineers' code can sometimes feel like an archaeology expedition, full of weird and wonderful statements that are hard to decipher. </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Code is always written with a purpose, but sometimes that purpose is not clear in the code itself.</span></span><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="vertical-align: baseline; white-space: pre-wrap;">You can address this knowledge gap by documenting the context that explains why a change was needed. Code comments provide context, but comments alone sometimes can’t provide enough.</span></span></span><br /> <span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span> <span id="docs-internal-guid-7555d281-72b5-f9ae-74c8-cbd8e1c6176b"><span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">There are two key ways to indicate context:</span></span></span><br /> <span id="docs-internal-guid-7555d281-72b6-2664-d850-c25d5e29af28"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">Commit Messages</span></span></span><br /> <br /> <ul> <li><span style="white-space: pre-wrap;"><b><span id="docs-internal-guid-7555d281-72b6-8d7f-0b46-1fa8c7bec68e" style="font-weight: normal;"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-weight: 700; vertical-align: baseline;"><span style="color: purple;">A commit message is one of the easiest, most discoverable</span></span><span style="color: #980000; font-weight: 700; vertical-align: baseline;"> </span><span style="vertical-align: baseline;">means of providing context. When you encounter lines of code that may be unclear, checking the commit message which introduced the code is a great way to gain more insight into what the code is meant to do.</span></span></span></b></span></li> <li><span style="font-family: "times" , "times new roman" , serif;"><span style="white-space: pre-wrap;"><b><span style="font-weight: normal;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-7555d281-72b7-48b7-d0de-75b127ea1f1d"><span style="color: purple;"><span style="font-weight: 700; vertical-align: baseline;">Write the first line of the commit message so it stands alone</span><span style="vertical-align: baseline;">,</span></span><span style="color: #980000; vertical-align: baseline;"> </span><span style="vertical-align: baseline;">as tools like GitHub will display this line in commit listing pages. Stand-alone first lines allow you to </span><span style="font-weight: 700; vertical-align: baseline;"><span style="color: purple;">skim through code history much faster</span></span><span style="vertical-align: baseline;">, quickly building up your understanding of how a source file evolved over time. </span></span></span></span></b></span><span id="docs-internal-guid-7555d281-72b7-d872-f4f6-c11333f0669d"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Example:</span><span style="color: #980000;"> </span></span></span> </span> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #cfe2f3; vertical-align: top; width: 607px;"><pre style="background-color: #cfe2f3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "courier new" , "courier" , monospace;">Add Frobber to the list of available widgets. This allows consumers to easily discover the new Frobber widget and add it to their application.</span></pre> </td></tr> </tbody></table> </div> </li> </ul> <div> <span id="docs-internal-guid-7555d281-72b9-5f39-e1a5-055ba3614359"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">Bug Reports</span></span></span></div> <div> <ul> <li><span style="white-space: pre-wrap;"><b><span id="docs-internal-guid-7555d281-72b9-bf82-7122-7cdf7b359c2a" style="font-weight: normal;"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-weight: 700; vertical-align: baseline;"><span style="color: purple;">You can use a bug report to track the entire story of a bug/feature/refactoring,</span></span><span style="vertical-align: baseline;"> adding context such as the original problem description, the design discussions between the team, and the commits that are used to solve the problem. This lets you easily see all related commits in one place, and allows others to easily keep track of the status of a particular problem.</span></span></span></b></span></li> <li><span style="white-space: pre-wrap;"><b><span style="font-weight: normal;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-7555d281-72ba-4b5b-1a53-71238d76987b"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-weight: 700; vertical-align: baseline;"><span style="color: purple;">Most commits should reference a bug report</span></span><span style="vertical-align: baseline;"><span style="color: purple;">.</span> Standalone commits (e.g. one-time cleanups or other small unplanned changes) don't need their own bug report, though, since they often contain all their context within the description and the source changes.</span></span></span></span></span></b></span></li> </ul> <div> <span id="docs-internal-guid-7555d281-72ba-7a34-c41b-ae90ca3524c5"><span style="font-family: "times" , "times new roman" , serif;"><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">I</span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">nformative commit messages and bug reports go hand-in-hand,</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"> providing context from different perspectives.</span><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="vertical-align: baseline; white-space: pre-wrap;">Keep in mind that such</span><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">context can be useful even to yourself</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">,</span> providing an easy reminder about the work you did last week, last quarter, or even last year. Future you will thank past you!</span></span></span></div> </div> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <span id="docs-internal-guid-96cdc92b-72a3-298c-9f87-daaddf19a3ec"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1Ub4xrBA6cyJjJ2bgFL7_VynlvJf423p7UBKIWBRMsnU/edit?usp=sharing" rel="nofollow" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> to display in your office.</span></span></span><br /> <span style="background-color: white; color: #222222; font-family: "arial"; font-size: 9.5pt; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">By Chris Lewis</span></span><br /> <span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span> <span id="docs-internal-guid-7555d281-72b2-27f4-085f-2b65456fdd8c"><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">You are caught in a trap. Mechanisms whirl around you, but they make no sense. You desperately search the room and find the builder's original plans! The description of the work order that implemented the trap reads, </span><span style="font-style: italic; vertical-align: baseline; white-space: pre-wrap;">"Miscellaneous fixes." </span><span style="vertical-align: baseline; white-space: pre-wrap;">Oh dear.</span></span></span><br /> <span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span> <span id="docs-internal-guid-7555d281-72b5-7098-346a-238d0acb67ad"><span style="font-family: "times" , "times new roman" , serif;"><span style="vertical-align: baseline; white-space: pre-wrap;">Reading other engineers' code can sometimes feel like an archaeology expedition, full of weird and wonderful statements that are hard to decipher. </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Code is always written with a purpose, but sometimes that purpose is not clear in the code itself.</span></span><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="vertical-align: baseline; white-space: pre-wrap;">You can address this knowledge gap by documenting the context that explains why a change was needed. Code comments provide context, but comments alone sometimes can’t provide enough.</span></span></span><br /> <span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span> <span id="docs-internal-guid-7555d281-72b5-f9ae-74c8-cbd8e1c6176b"><span style="vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">There are two key ways to indicate context:</span></span></span><br /> <span id="docs-internal-guid-7555d281-72b6-2664-d850-c25d5e29af28"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">Commit Messages</span></span></span><br /> <br /> <ul> <li><span style="white-space: pre-wrap;"><b><span id="docs-internal-guid-7555d281-72b6-8d7f-0b46-1fa8c7bec68e" style="font-weight: normal;"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-weight: 700; vertical-align: baseline;"><span style="color: purple;">A commit message is one of the easiest, most discoverable</span></span><span style="color: #980000; font-weight: 700; vertical-align: baseline;"> </span><span style="vertical-align: baseline;">means of providing context. When you encounter lines of code that may be unclear, checking the commit message which introduced the code is a great way to gain more insight into what the code is meant to do.</span></span></span></b></span></li> <li><span style="font-family: "times" , "times new roman" , serif;"><span style="white-space: pre-wrap;"><b><span style="font-weight: normal;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-7555d281-72b7-48b7-d0de-75b127ea1f1d"><span style="color: purple;"><span style="font-weight: 700; vertical-align: baseline;">Write the first line of the commit message so it stands alone</span><span style="vertical-align: baseline;">,</span></span><span style="color: #980000; vertical-align: baseline;"> </span><span style="vertical-align: baseline;">as tools like GitHub will display this line in commit listing pages. Stand-alone first lines allow you to </span><span style="font-weight: 700; vertical-align: baseline;"><span style="color: purple;">skim through code history much faster</span></span><span style="vertical-align: baseline;">, quickly building up your understanding of how a source file evolved over time. </span></span></span></span></b></span><span id="docs-internal-guid-7555d281-72b7-d872-f4f6-c11333f0669d"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Example:</span><span style="color: #980000;"> </span></span></span> </span> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #cfe2f3; vertical-align: top; width: 607px;"><pre style="background-color: #cfe2f3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "courier new" , "courier" , monospace;">Add Frobber to the list of available widgets. This allows consumers to easily discover the new Frobber widget and add it to their application.</span></pre> </td></tr> </tbody></table> </div> </li> </ul> <div> <span id="docs-internal-guid-7555d281-72b9-5f39-e1a5-055ba3614359"><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">Bug Reports</span></span></span></div> <div> <ul> <li><span style="white-space: pre-wrap;"><b><span id="docs-internal-guid-7555d281-72b9-bf82-7122-7cdf7b359c2a" style="font-weight: normal;"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-weight: 700; vertical-align: baseline;"><span style="color: purple;">You can use a bug report to track the entire story of a bug/feature/refactoring,</span></span><span style="vertical-align: baseline;"> adding context such as the original problem description, the design discussions between the team, and the commits that are used to solve the problem. This lets you easily see all related commits in one place, and allows others to easily keep track of the status of a particular problem.</span></span></span></b></span></li> <li><span style="white-space: pre-wrap;"><b><span style="font-weight: normal;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-7555d281-72ba-4b5b-1a53-71238d76987b"><span style="font-family: "times" , "times new roman" , serif;"><span style="font-weight: 700; vertical-align: baseline;"><span style="color: purple;">Most commits should reference a bug report</span></span><span style="vertical-align: baseline;"><span style="color: purple;">.</span> Standalone commits (e.g. one-time cleanups or other small unplanned changes) don't need their own bug report, though, since they often contain all their context within the description and the source changes.</span></span></span></span></span></b></span></li> </ul> <div> <span id="docs-internal-guid-7555d281-72ba-7a34-c41b-ae90ca3524c5"><span style="font-family: "times" , "times new roman" , serif;"><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">I</span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">nformative commit messages and bug reports go hand-in-hand,</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"> providing context from different perspectives.</span><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="vertical-align: baseline; white-space: pre-wrap;">Keep in mind that such</span><span style="color: #980000; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">context can be useful even to yourself</span></span><span style="vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">,</span> providing an easy reminder about the work you did last week, last quarter, or even last year. Future you will thank past you!</span></span></span></div> </div> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </noscript> </div> </div> <div class='share'> <span class='twitter-custom social-wrapper' data-href='http://twitter.com/share?text=Google Testing Blog:Code Health: Providing Context with Commit Messages and Bug Reports&url=https://testing.googleblog.com/2017/09/code-health-providing-context-with.html&via=googletesting'> <img alt='Share on Twitter' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_twitter_black_24dp.png' width='24'/> </span> <span class='fb-custom social-wrapper' data-href='https://www.facebook.com/sharer.php?u=https://testing.googleblog.com/2017/09/code-health-providing-context-with.html'> <img alt='Share on Facebook' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_facebook_black_24dp.png' width='24'/> </span> </div> <div class='comment-container'> <i class='comment-img material-icons'>  </i> <a href='https://testing.googleblog.com/2017/09/code-health-providing-context-with.html#comments' style='font-weight: 500; text-decoration: underline;'>3 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2017/09/code-health-providing-context-with.html' data-viewtype='FILTERED_POSTMOD'></div> <a href='https://plus.google.com/112374322230920073195' rel='author' style='display:none;'> Google </a> <div class='label-footer'> <span class='labels-caption'> Labels: </span> <span class='labels'> <a class='label' href='https://testing.googleblog.com/search/label/Chris%20Lewis' rel='tag'> Chris Lewis </a> , <a class='label' href='https://testing.googleblog.com/search/label/Code%20Health' rel='tag'> Code Health </a> , <a class='label' href='https://testing.googleblog.com/search/label/TotT' rel='tag'> TotT </a> </span> </div> </div> </div> <div class='post' data-id='1547713588878071210' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2017/08/code-health-eliminate-yagni-smells.html' itemprop='url' title='Code Health: Eliminate YAGNI Smells'> Code Health: Eliminate YAGNI Smells </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Monday, August 14, 2017 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span id="docs-internal-guid-2e5aeb06-e1f7-06a6-663b-93c217e243b7"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1ZDlgl15g5PHBZssnW_EHktx1gvfud0inVwQ4fmXQrL8/edit?usp=sharing" rel="nofollow" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> to display in your office.</span></span></span><br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;">By </span></span><span style="color: #222222; font-family: "times" , "times new roman" , serif;"><span style="white-space: pre-wrap;">Marc Eaddy</span></span><br /> <span style="color: #222222; font-family: "times" , "times new roman" , serif;"><span style="white-space: pre-wrap;"><br /></span></span> <span id="docs-internal-guid-6eaa5349-e1fc-8117-bf44-2d81283878fb"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">The majority of software development costs are due to maintenance.</span><span style="color: purple;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">One way to reduce maintenance costs is to </span><span style="background-color: white; font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">implement something only when you actually need it</span><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">, a.k.a. the </span><span style="background-color: white; font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">“You Aren't Gonna Need It”</span><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> (YAGNI) design principle.</span></span><span style="background-color: white; color: #980000; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">How do you spot unnecessary code? Follow your nose!</span></span></span><br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span> <span id="docs-internal-guid-6eaa5349-e1fd-1c9f-0067-350ede75aa2d"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">A </span><span style="background-color: white; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">code smell</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> is a code pattern that usually indicates a design flaw. For example, creating a base class or interface with only one subclass may indicate a speculation</span><span style="background-color: white; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">that more subclasses will be needed in the future. Instead, </span><span style="color: purple;"><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">practice </span><span style="background-color: white; font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">incremental development and design</span></span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">: don't add the second subclass until it is actually needed.</span></span></span><br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span> <span id="docs-internal-guid-6eaa5349-e1fd-bee8-4106-0eb06fd3b57e"><span style="color: purple; font-family: "times" , "times new roman" , serif;"><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">The following C++ code has many YAGNI smells</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">:</span></span></span><br /> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #cfe2f3; vertical-align: top; width: 607px;"><pre style="background-color: #cfe2f3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "courier new" , "courier" , monospace;">class Mammal { ... virtual Status Sleep(bool hibernate) = 0; }; class Human : public Mammal { ... virtual Status Sleep(bool hibernate) { age += hibernate ? kSevenMonths : kSevenHours; return OK; } };</span></pre> </td></tr> </tbody></table> </div> <br /> <span id="docs-internal-guid-6eaa5349-e206-b27d-31ae-50bf28cffdf8"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">Maintainers are burdened with understanding, documenting, and testing both classes when only one is really needed. Code must handle the case when </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">hibernate</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> is true, even though all callers pass </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">false</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">, as well as the case when</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">Sleep</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">returns an error, even though that never happens. This results in unnecessary code that never executes.</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: purple;"><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Eliminating those smells simplifies the code</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">:</span></span></span></span><br /> <div> <br /> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #d9ead3; vertical-align: top; width: 607px;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "courier new" , "courier" , monospace;">class Human { ... void Sleep() { age += kSevenHours; } };</span></pre> </td></tr> </tbody></table> </div> </div> <div> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;"><br /></span></span></span> <span id="docs-internal-guid-6eaa5349-e20a-75df-ea9f-425d9248d2b8"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Here are some other YAGNI smells</span></span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">:</span></span></span></div> <div> <ul> <li><span style="white-space: pre-wrap;"><span style="font-family: Times, Times New Roman, serif;">Code that has never been executed other than by tests (a.k.a. code that is dead on arrival)</span></span></li> <li><span style="white-space: pre-wrap;"><span style="font-family: Times, Times New Roman, serif;">Classes designed to be subclassed (have virtual methods and/or protected members) that are not actually subclassed</span></span></li> <li><span style="white-space: pre-wrap;"><span style="font-family: Times, Times New Roman, serif;">Public or protected methods or fields that could be private</span></span></li> <li><span style="font-family: Times, Times New Roman, serif; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">Parameters, variables, or flags that always have the same valu</span>e</span></li> </ul> <div> <span id="docs-internal-guid-6eaa5349-e20c-160d-42e8-867621960b75" style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">Thankfully, </span><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">YAGNI smells, and code smells in general, are often easy to spot by looking for simple patterns and are easy to eliminate using simple refactorings</span></span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">.</span></span></div> </div> <div> <span id="docs-internal-guid-6eaa5349-e20c-8481-d93e-91a798eaf368"></span><br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 10pt;"> <span id="docs-internal-guid-6eaa5349-e20c-8481-d93e-91a798eaf368"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">Are you thinking of adding code that won't be used today? Trust me, </span><span style="background-color: white; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">you aren't gonna need it!</span></span></span></div> <span id="docs-internal-guid-6eaa5349-e20c-8481-d93e-91a798eaf368"> </span> <br /> <div> <span id="docs-internal-guid-6eaa5349-e20c-8481-d93e-91a798eaf368"><span style="background-color: white; font-size: 13pt; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span></div> <span id="docs-internal-guid-6eaa5349-e20c-8481-d93e-91a798eaf368"> </span></div> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <span id="docs-internal-guid-2e5aeb06-e1f7-06a6-663b-93c217e243b7"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1ZDlgl15g5PHBZssnW_EHktx1gvfud0inVwQ4fmXQrL8/edit?usp=sharing" rel="nofollow" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> to display in your office.</span></span></span><br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;">By </span></span><span style="color: #222222; font-family: "times" , "times new roman" , serif;"><span style="white-space: pre-wrap;">Marc Eaddy</span></span><br /> <span style="color: #222222; font-family: "times" , "times new roman" , serif;"><span style="white-space: pre-wrap;"><br /></span></span> <span id="docs-internal-guid-6eaa5349-e1fc-8117-bf44-2d81283878fb"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">The majority of software development costs are due to maintenance.</span><span style="color: purple;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">One way to reduce maintenance costs is to </span><span style="background-color: white; font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">implement something only when you actually need it</span><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">, a.k.a. the </span><span style="background-color: white; font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">“You Aren't Gonna Need It”</span><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> (YAGNI) design principle.</span></span><span style="background-color: white; color: #980000; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">How do you spot unnecessary code? Follow your nose!</span></span></span><br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span> <span id="docs-internal-guid-6eaa5349-e1fd-1c9f-0067-350ede75aa2d"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">A </span><span style="background-color: white; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">code smell</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> is a code pattern that usually indicates a design flaw. For example, creating a base class or interface with only one subclass may indicate a speculation</span><span style="background-color: white; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">that more subclasses will be needed in the future. Instead, </span><span style="color: purple;"><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">practice </span><span style="background-color: white; font-style: italic; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">incremental development and design</span></span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">: don't add the second subclass until it is actually needed.</span></span></span><br /> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span> <span id="docs-internal-guid-6eaa5349-e1fd-bee8-4106-0eb06fd3b57e"><span style="color: purple; font-family: "times" , "times new roman" , serif;"><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">The following C++ code has many YAGNI smells</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">:</span></span></span><br /> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #cfe2f3; vertical-align: top; width: 607px;"><pre style="background-color: #cfe2f3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "courier new" , "courier" , monospace;">class Mammal { ... virtual Status Sleep(bool hibernate) = 0; }; class Human : public Mammal { ... virtual Status Sleep(bool hibernate) { age += hibernate ? kSevenMonths : kSevenHours; return OK; } };</span></pre> </td></tr> </tbody></table> </div> <br /> <span id="docs-internal-guid-6eaa5349-e206-b27d-31ae-50bf28cffdf8"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">Maintainers are burdened with understanding, documenting, and testing both classes when only one is really needed. Code must handle the case when </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">hibernate</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> is true, even though all callers pass </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">false</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">, as well as the case when</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">Sleep</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">returns an error, even though that never happens. This results in unnecessary code that never executes.</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: purple;"><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Eliminating those smells simplifies the code</span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">:</span></span></span></span><br /> <div> <br /> <div style="overflow-x: auto;"> <table class="my-bordered-table" style="width: 613px;"><tbody> <tr><td style="background-color: #d9ead3; vertical-align: top; width: 607px;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-top: 0px;"><span style="font-family: "courier new" , "courier" , monospace;">class Human { ... void Sleep() { age += kSevenHours; } };</span></pre> </td></tr> </tbody></table> </div> </div> <div> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;"><br /></span></span></span> <span id="docs-internal-guid-6eaa5349-e20a-75df-ea9f-425d9248d2b8"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Here are some other YAGNI smells</span></span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">:</span></span></span></div> <div> <ul> <li><span style="white-space: pre-wrap;"><span style="font-family: Times, Times New Roman, serif;">Code that has never been executed other than by tests (a.k.a. code that is dead on arrival)</span></span></li> <li><span style="white-space: pre-wrap;"><span style="font-family: Times, Times New Roman, serif;">Classes designed to be subclassed (have virtual methods and/or protected members) that are not actually subclassed</span></span></li> <li><span style="white-space: pre-wrap;"><span style="font-family: Times, Times New Roman, serif;">Public or protected methods or fields that could be private</span></span></li> <li><span style="font-family: Times, Times New Roman, serif; white-space: pre-wrap;"><span style="font-family: "times" , "times new roman" , serif;">Parameters, variables, or flags that always have the same valu</span>e</span></li> </ul> <div> <span id="docs-internal-guid-6eaa5349-e20c-160d-42e8-867621960b75" style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">Thankfully, </span><span style="background-color: white; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">YAGNI smells, and code smells in general, are often easy to spot by looking for simple patterns and are easy to eliminate using simple refactorings</span></span><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">.</span></span></div> </div> <div> <span id="docs-internal-guid-6eaa5349-e20c-8481-d93e-91a798eaf368"></span><br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 10pt;"> <span id="docs-internal-guid-6eaa5349-e20c-8481-d93e-91a798eaf368"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; vertical-align: baseline; white-space: pre-wrap;">Are you thinking of adding code that won't be used today? Trust me, </span><span style="background-color: white; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">you aren't gonna need it!</span></span></span></div> <span id="docs-internal-guid-6eaa5349-e20c-8481-d93e-91a798eaf368"> </span> <br /> <div> <span id="docs-internal-guid-6eaa5349-e20c-8481-d93e-91a798eaf368"><span style="background-color: white; font-size: 13pt; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span></div> <span id="docs-internal-guid-6eaa5349-e20c-8481-d93e-91a798eaf368"> </span></div> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </noscript> </div> </div> <div class='share'> <span class='twitter-custom social-wrapper' data-href='http://twitter.com/share?text=Google Testing Blog:Code Health: Eliminate YAGNI Smells&url=https://testing.googleblog.com/2017/08/code-health-eliminate-yagni-smells.html&via=googletesting'> <img alt='Share on Twitter' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_twitter_black_24dp.png' width='24'/> </span> <span class='fb-custom social-wrapper' data-href='https://www.facebook.com/sharer.php?u=https://testing.googleblog.com/2017/08/code-health-eliminate-yagni-smells.html'> <img alt='Share on Facebook' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_facebook_black_24dp.png' width='24'/> </span> </div> <div class='comment-container'> <i class='comment-img material-icons'>  </i> <a href='https://testing.googleblog.com/2017/08/code-health-eliminate-yagni-smells.html#comments' style='font-weight: 500; text-decoration: underline;'>1 comment</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2017/08/code-health-eliminate-yagni-smells.html' data-viewtype='FILTERED_POSTMOD'></div> <a href='https://plus.google.com/112374322230920073195' rel='author' style='display:none;'> Google </a> <div class='label-footer'> <span class='labels-caption'> Labels: </span> <span class='labels'> <a class='label' href='https://testing.googleblog.com/search/label/Code%20Health' rel='tag'> Code Health </a> , <a class='label' href='https://testing.googleblog.com/search/label/Marc%20Eaddy' rel='tag'> Marc Eaddy </a> , <a class='label' href='https://testing.googleblog.com/search/label/TotT' rel='tag'> TotT </a> </span> </div> </div> </div> <div class='post' data-id='5029073665609132906' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2017/07/code-health-to-comment-or-not-to-comment.html' itemprop='url' title='Code Health: To Comment or Not to Comment?'> Code Health: To Comment or Not to Comment? </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Monday, July 17, 2017 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span id="docs-internal-guid-f12e4fdc-518c-da84-eea8-b6a4be0fe25f"><i><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1ZgxLPQfKAfdwU-07sYplTWWnlzk6MaAxPMB1HpuOYdM/edit?usp=sharing" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;"> to display in your office. </span></span></i></span><br /> <span style="background-color: white; color: #222222; font-family: "arial"; font-size: 9.5pt; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;">By </span><span style="color: #222222;"><span style="white-space: pre-wrap;">Dori Reuveni and Kevin Bourrillion</span></span></span><br /> <span style="color: #222222; font-family: "arial";"><span style="font-size: 12.6667px; white-space: pre-wrap;"><i><br /></i></span></span> <span id="docs-internal-guid-80f4df1e-5195-7562-ccca-33b91dee58da"><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;">While reading code, </span><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">often there is nothing more helpful than a well-placed comment.</span></span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"> However, </span><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">comments are not always good.</span></span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"> Sometimes the need for a comment can be a sign that the code should be refactored.</span></span><br /> <span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span id="docs-internal-guid-80f4df1e-5199-e564-da1d-a76a06c36dc4"><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Use a comment when it is infeasible to make your code self-explanatory.</span></span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"> If you think you need a comment to explain what a piece of code does, first try one of the following:</span></span><br /> <ul style="padding-right:0;"><div dir="ltr" style="margin-left: 36pt;"> </div> <li style="overflow-x: auto;"><span style="white-space: pre-wrap;"><span id="docs-internal-guid-80f4df1e-519a-69a9-6808-90426cacd365"><span style="vertical-align: baseline;"><span style="font-size: 13pt;">Introduce an explaining variable.</span><table class="my-bordered-table"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Subtract discount from price.</span> finalPrice = (numItems * itemPrice) - min(5, numItems) * itemPrice * 0.1;</pre> </td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">price = numItems * itemPrice; discount = min(5, numItems) * itemPrice * 0.1; finalPrice = price - discount;</pre></td> </tr> </tbody></table> </span></span></span></li> <li style="overflow-x: auto;"><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-519f-4335-f8b0-d5a33dcb9da9"><span style="font-size: 13pt; vertical-align: baseline;">Extract a method. <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Filter offensive words.</span> for (String word : words) { ... }</pre></td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">filterOffensiveWords(words);</pre></td> </tr> </tbody></table> </span></span></span></span></li> <li style="overflow-x: auto;"><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a0-170b-6ea9-9f5c5276098e"><span style="vertical-align: baseline;"><span style="font-size: 13pt;">Use a more descriptive identifier name. </span><table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">int width = ...; <span style="font-weight: bold;">// Width in pixels. </span></pre></td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">int widthInPixels = ...;</pre></td> </tr> </tbody></table> <span style="font-size: 13pt;"> </span></span></span></span></span></li> <li style="overflow-x: auto;"><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a0-2ea1-3c01-7139b77b3d83"><span style="vertical-align: baseline;"><span style="font-size: 13pt;">Add a check in case your code has assumptions.</span> <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Safe since height is always > 0.</span> return width / height;</pre></td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">checkArgument(height > 0); return width / height; </pre></td> </tr> </tbody></table> <span style="font-size: 13pt;"> </span></span></span></span></span></li> </ul> <span id="docs-internal-guid-80f4df1e-51a0-8452-eab1-2cd24d48de26"><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">There are cases where a comment can be helpful:</span></span></span><br /> <div> <ul style="padding-right: 0;"> <li style="overflow-x: auto;"><span style="color: #980000;"><span style="font-size: 17.3333px; white-space: pre-wrap;"><b><span id="docs-internal-guid-80f4df1e-51a0-b549-18ae-18357c1b342e" style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;">Reveal your intent: explain </span><span style="color: black; font-size: 13pt; font-style: italic; vertical-align: baseline;">why</span><span style="color: black; font-size: 13pt; vertical-align: baseline;"> the code does something (as opposed to </span><span style="color: black; font-size: 13pt; font-style: italic; vertical-align: baseline;">what</span><span style="color: black; font-size: 13pt; vertical-align: baseline;"> it does). <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #d9ead3; vertical-align: top; width: 100%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Compute once because it’s expensive.</span></pre></td> </tr> </tbody></table> </span></span></b></span></span></li> <li style="overflow-x: auto;"><span style="color: #980000;"><span style="font-size: 17.3333px; white-space: pre-wrap;"><b><span style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a0-df5a-d7f5-d2b802cd8c8a"><span style="font-size: 13pt; vertical-align: baseline;">Protect a well-meaning future editor from mistakenly “fixing” your code.<b style="color: #980000; font-size: 17.3333px;"><span id="docs-internal-guid-80f4df1e-51a0-b549-18ae-18357c1b342e" style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"> <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #d9ead3; vertical-align: top; width: 100%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Create a new Foo instance because Foo is not thread-safe.</span></pre></td> </tr> </tbody></table> </span></span></b> </span></span></span></span></b></span></span></li> <li style="overflow-x: auto;"><span style="color: #980000;"><span style="font-size: 17.3333px; white-space: pre-wrap;"><b><span style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"><span style="font-size: 13pt; vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a1-2bf0-a976-6eff6b40c4c9"><span style="font-size: 13pt; vertical-align: baseline;">Clarification: a question that came up during code review or that readers of the code might have.<b style="color: #980000; font-size: 17.3333px;"><span style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a0-df5a-d7f5-d2b802cd8c8a"><span style="font-size: 13pt; vertical-align: baseline;"><b style="color: #980000; font-size: 17.3333px;"><span id="docs-internal-guid-80f4df1e-51a0-b549-18ae-18357c1b342e" style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"> <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #d9ead3; vertical-align: top; width: 100%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Note that order matters because...</span></pre></td> </tr> </tbody></table> </span></span></b></span></span></span></span></b> </span></span></span></span></span></b></span></span></li> <li style="overflow-x: auto;"><span style="vertical-align: baseline;"><span style="vertical-align: baseline;"><span style="font-size: 17.3333px; vertical-align: baseline; white-space: pre-wrap;">Explain your rationale for what looks like a bad software engineering practice.<b style="color: #980000; font-size: 17.3333px;"><span style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"><span style="font-size: 13pt; vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a1-2bf0-a976-6eff6b40c4c9"><span style="font-size: 13pt; vertical-align: baseline;"><b style="color: #980000; font-size: 17.3333px;"><span style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a0-df5a-d7f5-d2b802cd8c8a"><span style="font-size: 13pt; vertical-align: baseline;"><b style="color: #980000; font-size: 17.3333px;"><span id="docs-internal-guid-80f4df1e-51a0-b549-18ae-18357c1b342e" style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"> <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #d9ead3; vertical-align: top; width: 100%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">@SuppressWarnings("unchecked") <span style="font-weight: bold;">// The cast is safe because...</span></pre></td> </tr> </tbody></table> </span></span></b></span></span></span></span></b></span></span></span></span></span></b> </span></span></span></li> </ul> <span id="docs-internal-guid-80f4df1e-51a1-dc5e-5e8a-e7db89713222"><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;">On the other hand, </span><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">avoid comments that just repeat what the code does</span></span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">.</span> These are just noise:</span></span><br /> <div style="overflow-x: auto;"><table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Get all users.</span> userService.getAllUsers();</pre></td> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Check if the name is empty.</span> if (name.isEmpty()) { ... }</pre></td> </tr> </tbody></table></div> </div> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <span id="docs-internal-guid-f12e4fdc-518c-da84-eea8-b6a4be0fe25f"><i><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1ZgxLPQfKAfdwU-07sYplTWWnlzk6MaAxPMB1HpuOYdM/edit?usp=sharing" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;"> to display in your office. </span></span></i></span><br /> <span style="background-color: white; color: #222222; font-family: "arial"; font-size: 9.5pt; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white; color: #222222; vertical-align: baseline; white-space: pre-wrap;">By </span><span style="color: #222222;"><span style="white-space: pre-wrap;">Dori Reuveni and Kevin Bourrillion</span></span></span><br /> <span style="color: #222222; font-family: "arial";"><span style="font-size: 12.6667px; white-space: pre-wrap;"><i><br /></i></span></span> <span id="docs-internal-guid-80f4df1e-5195-7562-ccca-33b91dee58da"><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;">While reading code, </span><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">often there is nothing more helpful than a well-placed comment.</span></span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"> However, </span><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">comments are not always good.</span></span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"> Sometimes the need for a comment can be a sign that the code should be refactored.</span></span><br /> <span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"><br /></span> <span id="docs-internal-guid-80f4df1e-5199-e564-da1d-a76a06c36dc4"><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Use a comment when it is infeasible to make your code self-explanatory.</span></span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"> If you think you need a comment to explain what a piece of code does, first try one of the following:</span></span><br /> <ul style="padding-right:0;"><div dir="ltr" style="margin-left: 36pt;"> </div> <li style="overflow-x: auto;"><span style="white-space: pre-wrap;"><span id="docs-internal-guid-80f4df1e-519a-69a9-6808-90426cacd365"><span style="vertical-align: baseline;"><span style="font-size: 13pt;">Introduce an explaining variable.</span><table class="my-bordered-table"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Subtract discount from price.</span> finalPrice = (numItems * itemPrice) - min(5, numItems) * itemPrice * 0.1;</pre> </td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">price = numItems * itemPrice; discount = min(5, numItems) * itemPrice * 0.1; finalPrice = price - discount;</pre></td> </tr> </tbody></table> </span></span></span></li> <li style="overflow-x: auto;"><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-519f-4335-f8b0-d5a33dcb9da9"><span style="font-size: 13pt; vertical-align: baseline;">Extract a method. <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Filter offensive words.</span> for (String word : words) { ... }</pre></td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">filterOffensiveWords(words);</pre></td> </tr> </tbody></table> </span></span></span></span></li> <li style="overflow-x: auto;"><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a0-170b-6ea9-9f5c5276098e"><span style="vertical-align: baseline;"><span style="font-size: 13pt;">Use a more descriptive identifier name. </span><table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">int width = ...; <span style="font-weight: bold;">// Width in pixels. </span></pre></td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">int widthInPixels = ...;</pre></td> </tr> </tbody></table> <span style="font-size: 13pt;"> </span></span></span></span></span></li> <li style="overflow-x: auto;"><span style="white-space: pre-wrap;"><span style="vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a0-2ea1-3c01-7139b77b3d83"><span style="vertical-align: baseline;"><span style="font-size: 13pt;">Add a check in case your code has assumptions.</span> <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Safe since height is always > 0.</span> return width / height;</pre></td> <td style="background-color: #d9ead3; vertical-align: top; width: 50%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">checkArgument(height > 0); return width / height; </pre></td> </tr> </tbody></table> <span style="font-size: 13pt;"> </span></span></span></span></span></li> </ul> <span id="docs-internal-guid-80f4df1e-51a0-8452-eab1-2cd24d48de26"><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">There are cases where a comment can be helpful:</span></span></span><br /> <div> <ul style="padding-right: 0;"> <li style="overflow-x: auto;"><span style="color: #980000;"><span style="font-size: 17.3333px; white-space: pre-wrap;"><b><span id="docs-internal-guid-80f4df1e-51a0-b549-18ae-18357c1b342e" style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;">Reveal your intent: explain </span><span style="color: black; font-size: 13pt; font-style: italic; vertical-align: baseline;">why</span><span style="color: black; font-size: 13pt; vertical-align: baseline;"> the code does something (as opposed to </span><span style="color: black; font-size: 13pt; font-style: italic; vertical-align: baseline;">what</span><span style="color: black; font-size: 13pt; vertical-align: baseline;"> it does). <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #d9ead3; vertical-align: top; width: 100%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Compute once because it’s expensive.</span></pre></td> </tr> </tbody></table> </span></span></b></span></span></li> <li style="overflow-x: auto;"><span style="color: #980000;"><span style="font-size: 17.3333px; white-space: pre-wrap;"><b><span style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a0-df5a-d7f5-d2b802cd8c8a"><span style="font-size: 13pt; vertical-align: baseline;">Protect a well-meaning future editor from mistakenly “fixing” your code.<b style="color: #980000; font-size: 17.3333px;"><span id="docs-internal-guid-80f4df1e-51a0-b549-18ae-18357c1b342e" style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"> <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #d9ead3; vertical-align: top; width: 100%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Create a new Foo instance because Foo is not thread-safe.</span></pre></td> </tr> </tbody></table> </span></span></b> </span></span></span></span></b></span></span></li> <li style="overflow-x: auto;"><span style="color: #980000;"><span style="font-size: 17.3333px; white-space: pre-wrap;"><b><span style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"><span style="font-size: 13pt; vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a1-2bf0-a976-6eff6b40c4c9"><span style="font-size: 13pt; vertical-align: baseline;">Clarification: a question that came up during code review or that readers of the code might have.<b style="color: #980000; font-size: 17.3333px;"><span style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a0-df5a-d7f5-d2b802cd8c8a"><span style="font-size: 13pt; vertical-align: baseline;"><b style="color: #980000; font-size: 17.3333px;"><span id="docs-internal-guid-80f4df1e-51a0-b549-18ae-18357c1b342e" style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"> <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #d9ead3; vertical-align: top; width: 100%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Note that order matters because...</span></pre></td> </tr> </tbody></table> </span></span></b></span></span></span></span></b> </span></span></span></span></span></b></span></span></li> <li style="overflow-x: auto;"><span style="vertical-align: baseline;"><span style="vertical-align: baseline;"><span style="font-size: 17.3333px; vertical-align: baseline; white-space: pre-wrap;">Explain your rationale for what looks like a bad software engineering practice.<b style="color: #980000; font-size: 17.3333px;"><span style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"><span style="font-size: 13pt; vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a1-2bf0-a976-6eff6b40c4c9"><span style="font-size: 13pt; vertical-align: baseline;"><b style="color: #980000; font-size: 17.3333px;"><span style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"><span id="docs-internal-guid-80f4df1e-51a0-df5a-d7f5-d2b802cd8c8a"><span style="font-size: 13pt; vertical-align: baseline;"><b style="color: #980000; font-size: 17.3333px;"><span id="docs-internal-guid-80f4df1e-51a0-b549-18ae-18357c1b342e" style="font-weight: normal;"><span style="color: black; font-size: 13pt; vertical-align: baseline;"> <table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #d9ead3; vertical-align: top; width: 100%;"><pre style="background-color: #d9ead3; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;">@SuppressWarnings("unchecked") <span style="font-weight: bold;">// The cast is safe because...</span></pre></td> </tr> </tbody></table> </span></span></b></span></span></span></span></b></span></span></span></span></span></b> </span></span></span></li> </ul> <span id="docs-internal-guid-80f4df1e-51a1-dc5e-5e8a-e7db89713222"><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;">On the other hand, </span><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">avoid comments that just repeat what the code does</span></span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">.</span> These are just noise:</span></span><br /> <div style="overflow-x: auto;"><table class="my-bordered-table" style="width: 100%;"> <tbody> <tr> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Get all users.</span> userService.getAllUsers();</pre></td> <td style="background-color: #f4cccc; vertical-align: top; width: 50%;"><pre style="background-color: #f4cccc; border: 0px; color: black; margin-bottom: 0; margin-top: 0; padding-bottom: 0; padding-top: 0; padding-left: 0;"><span style="font-weight: bold;">// Check if the name is empty.</span> if (name.isEmpty()) { ... }</pre></td> </tr> </tbody></table></div> </div> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </noscript> </div> </div> <div class='share'> <span class='twitter-custom social-wrapper' data-href='http://twitter.com/share?text=Google Testing Blog:Code Health: To Comment or Not to Comment?&url=https://testing.googleblog.com/2017/07/code-health-to-comment-or-not-to-comment.html&via=googletesting'> <img alt='Share on Twitter' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_twitter_black_24dp.png' width='24'/> </span> <span class='fb-custom social-wrapper' data-href='https://www.facebook.com/sharer.php?u=https://testing.googleblog.com/2017/07/code-health-to-comment-or-not-to-comment.html'> <img alt='Share on Facebook' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_facebook_black_24dp.png' width='24'/> </span> </div> <div class='comment-container'> <i class='comment-img material-icons'>  </i> <a href='https://testing.googleblog.com/2017/07/code-health-to-comment-or-not-to-comment.html#comments' style='font-weight: 500; text-decoration: underline;'>10 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2017/07/code-health-to-comment-or-not-to-comment.html' data-viewtype='FILTERED_POSTMOD'></div> <a href='https://plus.google.com/112374322230920073195' rel='author' style='display:none;'> Google </a> <div class='label-footer'> <span class='labels-caption'> Labels: </span> <span class='labels'> <a class='label' href='https://testing.googleblog.com/search/label/Code%20Health' rel='tag'> Code Health </a> , <a class='label' href='https://testing.googleblog.com/search/label/Dori%20Reuveni' rel='tag'> Dori Reuveni </a> , <a class='label' href='https://testing.googleblog.com/search/label/Kevin%20Bourrillion' rel='tag'> Kevin Bourrillion </a> , <a class='label' href='https://testing.googleblog.com/search/label/TotT' rel='tag'> TotT </a> </span> </div> </div> </div> <div class='post' data-id='3343661551924942594' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2017/07/evolution-of-gtac-and-engineering.html' itemprop='url' title='Evolution of GTAC and Engineering Productivity'> Evolution of GTAC and Engineering Productivity </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Wednesday, July 12, 2017 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">When Google first hosted GTAC in 2006, we didn’t know what to expect. We kicked off this conference with the intention to share our innovation in test automation, learn from others in the industry and connect with academia. Over the last decade we’ve had great participation and had the privilege to host GTAC in North America, Europe and Asia -- largely thanks to the many of you who spoke, participated and connected!</span></div> <b id="docs-internal-guid-b2800243-380a-1c76-0e2a-b9be11aa8164" style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In the recent months, we’ve been taking a hard look at the discipline of </span><a href="https://testing.googleblog.com/2016/03/from-qa-to-engineering-productivity.html" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Engineering Productivity</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> as a logical next step in the evolution of test automation. In that same vein, we’re going to rethink what an Engineering Productivity focused conference should look like today. As we pivot, we will be extending these changes to GTAC and because we expect changes in theme, content and format, we are canceling the upcoming event scheduled in London this November. We’ll be bringing the event back in 2018 with a fresh outlook and strategy. </span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">While we know this may be disappointing for many of the folks who were looking forward to GTAC, we’re excited to come back with a new format which will serve this conference well in today’s environment.</span></div> <br /> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">When Google first hosted GTAC in 2006, we didn’t know what to expect. We kicked off this conference with the intention to share our innovation in test automation, learn from others in the industry and connect with academia. Over the last decade we’ve had great participation and had the privilege to host GTAC in North America, Europe and Asia -- largely thanks to the many of you who spoke, participated and connected!</span></div> <b id="docs-internal-guid-b2800243-380a-1c76-0e2a-b9be11aa8164" style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In the recent months, we’ve been taking a hard look at the discipline of </span><a href="https://testing.googleblog.com/2016/03/from-qa-to-engineering-productivity.html" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Engineering Productivity</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> as a logical next step in the evolution of test automation. In that same vein, we’re going to rethink what an Engineering Productivity focused conference should look like today. As we pivot, we will be extending these changes to GTAC and because we expect changes in theme, content and format, we are canceling the upcoming event scheduled in London this November. We’ll be bringing the event back in 2018 with a fresh outlook and strategy. </span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">While we know this may be disappointing for many of the folks who were looking forward to GTAC, we’re excited to come back with a new format which will serve this conference well in today’s environment.</span></div> <br /> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </noscript> </div> </div> <div class='share'> <span class='twitter-custom social-wrapper' data-href='http://twitter.com/share?text=Google Testing Blog:Evolution of GTAC and Engineering Productivity&url=https://testing.googleblog.com/2017/07/evolution-of-gtac-and-engineering.html&via=googletesting'> <img alt='Share on Twitter' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_twitter_black_24dp.png' width='24'/> </span> <span class='fb-custom social-wrapper' data-href='https://www.facebook.com/sharer.php?u=https://testing.googleblog.com/2017/07/evolution-of-gtac-and-engineering.html'> <img alt='Share on Facebook' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_facebook_black_24dp.png' width='24'/> </span> </div> <div class='comment-container'> <i class='comment-img material-icons'>  </i> <a href='https://testing.googleblog.com/2017/07/evolution-of-gtac-and-engineering.html#comments' style='font-weight: 500; text-decoration: underline;'>34 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2017/07/evolution-of-gtac-and-engineering.html' data-viewtype='FILTERED_POSTMOD'></div> <a href='https://plus.google.com/112374322230920073195' rel='author' style='display:none;'> Google </a> <div class='label-footer'> <span class='labels-caption'> Labels: </span> <span class='labels'> <a class='label' href='https://testing.googleblog.com/search/label/GTAC' rel='tag'> GTAC </a> </span> </div> </div> </div> <div class='post' data-id='841381449055719530' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2017/06/code-health-too-many-comments-on-your.html' itemprop='url' title='Code Health: Too Many Comments on Your Code Reviews?'> Code Health: Too Many Comments on Your Code Reviews? </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Monday, June 19, 2017 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span id="docs-internal-guid-19e757bc-c15c-9682-a581-e80a1c1cb3fe" style="font-family: inherit;"><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1DnJl_Xt5xddfOU5JESq4Q5PvKKDMoDBxmrQFjColVpk/edit?usp=sharing" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> to display in your office. </span></span><br /> <span style="background-color: white; color: #222222; font-size: 9.5pt; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;"><br /></span></span> <span style="font-family: inherit;"><span style="color: #222222;"><span style="background-color: white; white-space: pre-wrap;">By </span></span><span style="color: #222222;"><span style="white-space: pre-wrap;">Tom O'Neill</span></span></span><br /> <span style="font-family: inherit;"><span style="color: #222222; font-family: inherit;"><span style="white-space: pre-wrap;"><br /></span></span> </span><br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: inherit; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Code reviews can slow down an individual code change, but they’re also an opportunity to improve your code and learn from another intelligent, experienced engineer. How can you get the most out of them?</span></div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Aim to get most of your changes approved in the first round of review, with only minor comments. </span><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">If your code reviews frequently require multiple rounds of comments, these tips can save you time.</span></span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span></span></div> <span style="font-family: inherit;"><span id="docs-internal-guid-baa04f06-c162-76ad-3d0e-c16973815eba"></span><br /></span> <br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Spend your reviewers’ time wisely—it’s a limited resource.</span></span><span style="background-color: transparent; color: #980000; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">If they’re catching issues that you could easily have caught yourself, you’re lowering the overall productivity of your team.</span></span></div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: inherit; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Before you send out the code review:</span></div> <ul style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Re-evaluate your code:</span></span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> Don’t just send the review out as soon as the tests pass. Step back and try to rethink the whole thing—can the design be cleaned up? Especially if it’s late in the day, see if a better approach occurs to you the next morning. Although this step might slow down an individual code change, it will result long-term in greater average throughput.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Consider an informal design discussion:</span></span><span style="background-color: transparent; color: #980000; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">If there’s something you’re not sure about, pair program, talk face-to-face, or send an early diff and ask for a “pre-review” of the overall design.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Self-review the change:</span></span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> Try to look at the code as critically as possible from the standpoint of someone who doesn’t know anything about it. Your code review tool can give you a radically different view of your code than the IDE. This can easily save you a round trip.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Make the diff easy to understand:</span></span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> Multiple changes at once make the code harder to review. When you self-review, look for simple changes that reduce the size of the diff. For example, save significant refactoring or formatting changes for another code review.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Don’t hide important info in the submit message:</span></span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"> Put it in the code as well. Someone reading the code later is unlikely to look at the submit message.</span></span></div> </li> </ul> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: inherit; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">When you’re addressing code review comments:</span></div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span id="docs-internal-guid-baa04f06-c164-b2b4-fc66-88b0be942bfa" style="font-family: inherit;"></span></span></div> <ul style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Re-evaluate your code after addressing non-trivial comments:</span></span><span style="background-color: transparent; color: #980000; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Take a step back and really look at the code with fresh eyes. Once you’ve made one set of changes, you can often find additional improvements that are enabled or suggested by those changes. Just as with any refactoring, it may take several steps to reach the best design.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="color: purple;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Understand </span><span style="background-color: transparent; font-size: 13pt; font-style: italic; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">why</span><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> the reviewer made each comment:</span></span><span style="background-color: transparent; color: #980000; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">If you don’t understand the reasoning behind a comment, don’t just make the change—seek out the reviewer and learn something new.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="color: purple;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Answer the reviewer’s questions in the </span><span style="background-color: transparent; font-size: 13pt; font-style: italic; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">code</span><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">:</span></span><span style="background-color: transparent; color: #980000; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Don’t just reply—make the code easier to understand (e.g., improve a variable name, change a boolean to an enum) or add a comment. Someone else is going to have the same question later on.</span></span></div> </li> </ul> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <span id="docs-internal-guid-19e757bc-c15c-9682-a581-e80a1c1cb3fe" style="font-family: inherit;"><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">This is another post in our </span><a href="https://testing.googleblog.com/2017/04/code-health-googles-internal-code.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Code Health</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> series. A version of this post originally appeared in Google bathrooms worldwide as a Google </span><a href="https://testing.googleblog.com/2007/01/introducing-testing-on-toilet.html" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">Testing on the Toilet</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> episode. You can download a </span><a href="https://docs.google.com/document/d/1DnJl_Xt5xddfOU5JESq4Q5PvKKDMoDBxmrQFjColVpk/edit?usp=sharing" style="text-decoration-line: none;"><span style="background-color: white; color: #1155cc; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">printer-friendly version</span></a><span style="background-color: white; color: #222222; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> to display in your office. </span></span><br /> <span style="background-color: white; color: #222222; font-size: 9.5pt; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;"><br /></span></span> <span style="font-family: inherit;"><span style="color: #222222;"><span style="background-color: white; white-space: pre-wrap;">By </span></span><span style="color: #222222;"><span style="white-space: pre-wrap;">Tom O'Neill</span></span></span><br /> <span style="font-family: inherit;"><span style="color: #222222; font-family: inherit;"><span style="white-space: pre-wrap;"><br /></span></span> </span><br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: inherit; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Code reviews can slow down an individual code change, but they’re also an opportunity to improve your code and learn from another intelligent, experienced engineer. How can you get the most out of them?</span></div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Aim to get most of your changes approved in the first round of review, with only minor comments. </span><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">If your code reviews frequently require multiple rounds of comments, these tips can save you time.</span></span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span></span></div> <span style="font-family: inherit;"><span id="docs-internal-guid-baa04f06-c162-76ad-3d0e-c16973815eba"></span><br /></span> <br /> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Spend your reviewers’ time wisely—it’s a limited resource.</span></span><span style="background-color: transparent; color: #980000; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">If they’re catching issues that you could easily have caught yourself, you’re lowering the overall productivity of your team.</span></span></div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: inherit; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Before you send out the code review:</span></div> <ul style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Re-evaluate your code:</span></span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> Don’t just send the review out as soon as the tests pass. Step back and try to rethink the whole thing—can the design be cleaned up? Especially if it’s late in the day, see if a better approach occurs to you the next morning. Although this step might slow down an individual code change, it will result long-term in greater average throughput.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Consider an informal design discussion:</span></span><span style="background-color: transparent; color: #980000; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">If there’s something you’re not sure about, pair program, talk face-to-face, or send an early diff and ask for a “pre-review” of the overall design.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Self-review the change:</span></span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> Try to look at the code as critically as possible from the standpoint of someone who doesn’t know anything about it. Your code review tool can give you a radically different view of your code than the IDE. This can easily save you a round trip.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Make the diff easy to understand:</span></span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> Multiple changes at once make the code harder to review. When you self-review, look for simple changes that reduce the size of the diff. For example, save significant refactoring or formatting changes for another code review.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="font-size: 13pt; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Don’t hide important info in the submit message:</span></span><span style="font-size: 13pt; vertical-align: baseline; white-space: pre-wrap;"> Put it in the code as well. Someone reading the code later is unlikely to look at the submit message.</span></span></div> </li> </ul> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: inherit; font-size: 13pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">When you’re addressing code review comments:</span></div> <div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span id="docs-internal-guid-baa04f06-c164-b2b4-fc66-88b0be942bfa" style="font-family: inherit;"></span></span></div> <ul style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="color: purple;">Re-evaluate your code after addressing non-trivial comments:</span></span><span style="background-color: transparent; color: #980000; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Take a step back and really look at the code with fresh eyes. Once you’ve made one set of changes, you can often find additional improvements that are enabled or suggested by those changes. Just as with any refactoring, it may take several steps to reach the best design.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="color: purple;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Understand </span><span style="background-color: transparent; font-size: 13pt; font-style: italic; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">why</span><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> the reviewer made each comment:</span></span><span style="background-color: transparent; color: #980000; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">If you don’t understand the reasoning behind a comment, don’t just make the change—seek out the reviewer and learn something new.</span></span></div> </li> <li dir="ltr" style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 10pt; margin-top: 0pt;"> <span style="font-family: inherit;"><span style="color: purple;"><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Answer the reviewer’s questions in the </span><span style="background-color: transparent; font-size: 13pt; font-style: italic; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">code</span><span style="background-color: transparent; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">:</span></span><span style="background-color: transparent; color: #980000; font-size: 13pt; font-style: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: black; font-size: 13pt; font-style: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Don’t just reply—make the code easier to understand (e.g., improve a variable name, change a boolean to an enum) or add a comment. Someone else is going to have the same question later on.</span></span></div> </li> </ul> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </noscript> </div> </div> <div class='share'> <span class='twitter-custom social-wrapper' data-href='http://twitter.com/share?text=Google Testing Blog:Code Health: Too Many Comments on Your Code Reviews?&url=https://testing.googleblog.com/2017/06/code-health-too-many-comments-on-your.html&via=googletesting'> <img alt='Share on Twitter' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_twitter_black_24dp.png' width='24'/> </span> <span class='fb-custom social-wrapper' data-href='https://www.facebook.com/sharer.php?u=https://testing.googleblog.com/2017/06/code-health-too-many-comments-on-your.html'> <img alt='Share on Facebook' height='24' src='https://www.gstatic.com/images/icons/material/system/2x/post_facebook_black_24dp.png' width='24'/> </span> </div> <div class='comment-container'> <i class='comment-img material-icons'>  </i> <a href='https://testing.googleblog.com/2017/06/code-health-too-many-comments-on-your.html#comments' style='font-weight: 500; text-decoration: underline;'>15 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2017/06/code-health-too-many-comments-on-your.html' data-viewtype='FILTERED_POSTMOD'></div> <a href='https://plus.google.com/112374322230920073195' rel='author' style='display:none;'> Google </a> <div class='label-footer'> <span class='labels-caption'> Labels: </span> <span class='labels'> <a class='label' href='https://testing.googleblog.com/search/label/Code%20Health' rel='tag'> Code Health </a> , <a class='label' href='https://testing.googleblog.com/search/label/Tom%20O%27Neill' rel='tag'> Tom O'Neill </a> , <a class='label' href='https://testing.googleblog.com/search/label/TotT' rel='tag'> TotT </a> </span> </div> </div> </div> <div class='blog-pager' id='blog-pager'> <a class='home-link' href='https://testing.googleblog.com/'> <i class='material-icons'>  </i> </a> <span id='blog-pager-newer-link'> <a class='blog-pager-newer-link' href='https://testing.googleblog.com/search?updated-max=2018-09-17T10:33:00-07:00&max-results=5&reverse-paginate=true' id='Blog1_blog-pager-newer-link' title='Newer Posts'> <i class='material-icons'>  </i> </a> </span> <span id='blog-pager-older-link'> <a class='blog-pager-older-link' href='https://testing.googleblog.com/search?updated-max=2017-06-19T10:47:00-07:00&max-results=5' id='Blog1_blog-pager-older-link' title='Older Posts'> <i class='material-icons'>  </i> </a> </span> </div> <div class='clear'></div> </div></div> </div> </div> <div class='col-right'> <div class='section' id='sidebar-top'><div class='widget HTML' data-version='1' id='HTML8'> <div class='widget-content'> <div class='searchBox'> <input type='text' title='Search This Blog' placeholder='Search blog ...' /> </div> </div> <div class='clear'></div> </div> </div> <div id='aside'> <div class='section' id='sidebar'><div class='widget Label' data-version='1' id='Label1'> <div class='tab'> <img class='sidebar-icon' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAYpJREFUeNrs2aFuwzAQBmAvKRkMKRjZA4QMDJaWFgyMjuzFRg37DIUlA3uFkoGQSaWzJU+tpri5O9+l/zSfdFJlpe59yTmyVedq1PjfcZMZ70NuQnaF8w8htyE/rABtpviXkLcK88c5HhLkMBfgVan43zfFBNGMjHVGT/s55KP2pAvidbGHd+nzKt1RKSLG3rKF1iPFv6UWiPke8i7kEqGdGsI1O+LYVdqJAjgirwkKYD0ytkJBUNbAMvX8V3q9PhUsYvU1sWD8SO/sQvx2ahxOiNoJCSBCoAHYCEQAC4EKICOQASQEOmAS8RcAFxFN5hiIiugpgC3wk9hQAHH/70EBHXUN7IER5EWMiBgo2+nzOKQv9SCAeEM/OQAkhE/ncccFICB87qzQMia5FsJfOui0zMnmRvipU1ormHQuxGTxUsAcCFLxJQBLBLn4UoAFglW8BkATwS5eC6CBEBWvCShBiIvXBkgQRcVbADiI4uKtABSESvGWgB9EzHt3+tNwyO0qa9SoIYtvAQYAqDJhaWWeMecAAAAASUVORK5CYII='/> <h2> Labels </h2> <i class='material-icons arrow'>  </i> </div> <div class='widget-content list-label-widget-content'> <ul> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/TotT'> TotT </a> <span dir='ltr'> 102 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/GTAC'> GTAC </a> <span dir='ltr'> 61 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/James%20Whittaker'> James Whittaker </a> <span dir='ltr'> 42 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Misko%20Hevery'> Misko Hevery </a> <span dir='ltr'> 32 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Code%20Health'> Code Health </a> <span dir='ltr'> 30 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Anthony%20Vallone'> Anthony Vallone </a> <span dir='ltr'> 27 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Patrick%20Copeland'> Patrick Copeland </a> <span dir='ltr'> 23 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jobs'> Jobs </a> <span dir='ltr'> 18 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Andrew%20Trenk'> Andrew Trenk </a> <span dir='ltr'> 12 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/C%2B%2B'> C++ </a> <span dir='ltr'> 11 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Patrik%20H%C3%B6glund'> Patrik Höglund </a> <span dir='ltr'> 8 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/JavaScript'> JavaScript </a> <span dir='ltr'> 7 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Allen%20Hutchison'> Allen Hutchison </a> <span dir='ltr'> 6 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/George%20Pirocanac'> George Pirocanac </a> <span dir='ltr'> 6 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Zhanyong%20Wan'> Zhanyong Wan </a> <span dir='ltr'> 6 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Harry%20Robinson'> Harry Robinson </a> <span dir='ltr'> 5 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Java'> Java </a> <span dir='ltr'> 5 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Julian%20Harty'> Julian Harty </a> <span dir='ltr'> 5 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Adam%20Bender'> Adam Bender </a> <span dir='ltr'> 4 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Alberto%20Savoia'> Alberto Savoia </a> <span dir='ltr'> 4 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Ben%20Yu'> Ben Yu </a> <span dir='ltr'> 4 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Erik%20Kuefler'> Erik Kuefler </a> <span dir='ltr'> 4 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Philip%20Zembrod'> Philip Zembrod </a> <span dir='ltr'> 4 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Shyam%20Seshadri'> Shyam Seshadri </a> <span dir='ltr'> 4 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Chrome'> Chrome </a> <span dir='ltr'> 3 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Dillon%20Bly'> Dillon Bly </a> <span dir='ltr'> 3 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/John%20Thomas'> John Thomas </a> <span dir='ltr'> 3 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Lesley%20Katzen'> Lesley Katzen </a> <span dir='ltr'> 3 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Marc%20Kaplan'> Marc Kaplan </a> <span dir='ltr'> 3 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Markus%20Clermont'> Markus Clermont </a> <span dir='ltr'> 3 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Max%20Kanat-Alexander'> Max Kanat-Alexander </a> <span dir='ltr'> 3 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Sonal%20Shah'> Sonal Shah </a> <span dir='ltr'> 3 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/APIs'> APIs </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Abhishek%20Arya'> Abhishek Arya </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Alan%20Myrvold'> Alan Myrvold </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Alek%20Icev'> Alek Icev </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Android'> Android </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/April%20Fools'> April Fools </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Chaitali%20Narla'> Chaitali Narla </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Chris%20Lewis'> Chris Lewis </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Chrome%20OS'> Chrome OS </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Diego%20Salas'> Diego Salas </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Dori%20Reuveni'> Dori Reuveni </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jason%20Arbon'> Jason Arbon </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jochen%20Wuttke'> Jochen Wuttke </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Kostya%20Serebryany'> Kostya Serebryany </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Marc%20Eaddy'> Marc Eaddy </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Marko%20Ivankovi%C4%87'> Marko Ivanković </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Mobile'> Mobile </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Oliver%20Chang'> Oliver Chang </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Simon%20Stewart'> Simon Stewart </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Stefan%20Kennedy'> Stefan Kennedy </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Test%20Flakiness'> Test Flakiness </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Titus%20Winters'> Titus Winters </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Tony%20Voellm'> Tony Voellm </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/WebRTC'> WebRTC </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Yiming%20Sun'> Yiming Sun </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Yvette%20Nameth'> Yvette Nameth </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Zuri%20Kemp'> Zuri Kemp </a> <span dir='ltr'> 2 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Aaron%20Jacobs'> Aaron Jacobs </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Adam%20Porter'> Adam Porter </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Adam%20Raider'> Adam Raider </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Adel%20Saoud'> Adel Saoud </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Alan%20Faulkner'> Alan Faulkner </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Alex%20Eagle'> Alex Eagle </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Amy%20Fu'> Amy Fu </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Anantha%20Keesara'> Anantha Keesara </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Antoine%20Picard'> Antoine Picard </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/App%20Engine'> App Engine </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Ari%20Shamash'> Ari Shamash </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Arif%20Sukoco'> Arif Sukoco </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Benjamin%20Pick'> Benjamin Pick </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Bob%20Nystrom'> Bob Nystrom </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Bruce%20Leban'> Bruce Leban </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Carlos%20Arguelles'> Carlos Arguelles </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Carlos%20Israel%20Ortiz%20Garc%C3%ADa'> Carlos Israel Ortiz García </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Cathal%20Weakliam'> Cathal Weakliam </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Christopher%20Semturs'> Christopher Semturs </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Clay%20Murphy'> Clay Murphy </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Dagang%20Wei'> Dagang Wei </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Dan%20Maksimovich'> Dan Maksimovich </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Dan%20Shi'> Dan Shi </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Dan%20Willemsen'> Dan Willemsen </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Dave%20Chen'> Dave Chen </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Dave%20Gladfelter'> Dave Gladfelter </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/David%20Bendory'> David Bendory </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/David%20Mandelberg'> David Mandelberg </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Derek%20Snyder'> Derek Snyder </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Diego%20Cavalcanti'> Diego Cavalcanti </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Dmitry%20Vyukov'> Dmitry Vyukov </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Eduardo%20Bravo%20Ortiz'> Eduardo Bravo Ortiz </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Ekaterina%20Kamenskaya'> Ekaterina Kamenskaya </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Elliott%20Karpilovsky'> Elliott Karpilovsky </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Elliotte%20Rusty%20Harold'> Elliotte Rusty Harold </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Espresso'> Espresso </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Felipe%20Sodr%C3%A9'> Felipe Sodré </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Francois%20Aube'> Francois Aube </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Gene%20Volovich'> Gene Volovich </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Google%2B'> Google+ </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Goran%20Petrovic'> Goran Petrovic </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Goranka%20Bjedov'> Goranka Bjedov </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Hank%20Duan'> Hank Duan </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Havard%20Rast%20Blok'> Havard Rast Blok </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Hongfei%20Ding'> Hongfei Ding </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jason%20Elbaum'> Jason Elbaum </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jason%20Huggins'> Jason Huggins </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jay%20Han'> Jay Han </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jeff%20Hoy'> Jeff Hoy </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jeff%20Listfield'> Jeff Listfield </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jessica%20Tomechak'> Jessica Tomechak </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jim%20Reardon'> Jim Reardon </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Joe%20Allan%20Muharsky'> Joe Allan Muharsky </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Joel%20Hynoski'> Joel Hynoski </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/John%20Micco'> John Micco </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/John%20Penix'> John Penix </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jonathan%20Rockway'> Jonathan Rockway </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Jonathan%20Velasquez'> Jonathan Velasquez </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Josh%20Armour'> Josh Armour </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Julie%20Ralph'> Julie Ralph </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Kai%20Kent'> Kai Kent </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Karin%20Lundberg'> Karin Lundberg </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Kaue%20Silveira'> Kaue Silveira </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Kevin%20Bourrillion'> Kevin Bourrillion </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Kevin%20Graney'> Kevin Graney </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Kirkland'> Kirkland </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Kurt%20Alfred%20Kluever'> Kurt Alfred Kluever </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Manjusha%20Parvathaneni'> Manjusha Parvathaneni </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Marek%20Kiszkis'> Marek Kiszkis </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Marius%20Latinis'> Marius Latinis </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Mark%20Ivey'> Mark Ivey </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Mark%20Manley'> Mark Manley </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Mark%20Striebeck'> Mark Striebeck </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Matt%20Lowrie'> Matt Lowrie </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Meredith%20Whittaker'> Meredith Whittaker </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Michael%20Bachman'> Michael Bachman </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Michael%20Klepikov'> Michael Klepikov </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Mike%20Aizatsky'> Mike Aizatsky </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Mike%20Wacker'> Mike Wacker </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Mona%20El%20Mahdy'> Mona El Mahdy </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Noel%20Yap'> Noel Yap </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Palak%20Bansal'> Palak Bansal </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Patricia%20Legaspi'> Patricia Legaspi </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Per%20Jacobsson'> Per Jacobsson </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Peter%20Arrenbrecht'> Peter Arrenbrecht </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Peter%20Spragins'> Peter Spragins </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Phil%20Norman'> Phil Norman </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Phil%20Rollet'> Phil Rollet </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Pooja%20Gupta'> Pooja Gupta </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Project%20Showcase'> Project Showcase </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Radoslav%20Vasilev'> Radoslav Vasilev </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Rajat%20Dewan'> Rajat Dewan </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Rajat%20Jain'> Rajat Jain </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Rich%20Martin'> Rich Martin </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Richard%20Bustamante'> Richard Bustamante </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Roshan%20Sembacuttiaratchy'> Roshan Sembacuttiaratchy </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Ruslan%20Khamitov'> Ruslan Khamitov </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Sam%20Lee'> Sam Lee </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Sean%20Jordan'> Sean Jordan </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Sharon%20Zhou'> Sharon Zhou </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Shiva%20Garg'> Shiva Garg </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Siddartha%20Janga'> Siddartha Janga </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Simran%20Basi'> Simran Basi </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Stan%20Chan'> Stan Chan </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Stephen%20Ng'> Stephen Ng </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Tejas%20Shah'> Tejas Shah </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Test%20Analytics'> Test Analytics </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Test%20Engineer'> Test Engineer </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Tim%20Lyakhovetskiy'> Tim Lyakhovetskiy </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Tom%20O%27Neill'> Tom O'Neill </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/Vojta%20J%C3%ADna'> Vojta Jína </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/automation'> automation </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/dead%20code'> dead code </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/iOS'> iOS </a> <span dir='ltr'> 1 </span> </li> <li> <a dir='ltr' href='https://testing.googleblog.com/search/label/mutation%20testing'> mutation testing </a> <span dir='ltr'> 1 </span> </li> </ul> <div class='clear'></div> </div> </div><div class='widget BlogArchive' data-version='1' id='BlogArchive1'> <div class='tab'> <i class='material-icons icon'>  </i> <h2> Archive </h2> <i class='material-icons arrow'>  </i> </div> <div class='widget-content'> <div id='ArchiveList'> <div id='BlogArchive1_ArchiveList'> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2024/'> 2024 </a> <span class='post-count' dir='ltr'>(12)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2024/10/'> Oct </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2024/09/'> Sep </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2024/08/'> Aug </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2024/07/'> Jul </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2024/05/'> May </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2024/04/'> Apr </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2024/03/'> Mar </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2024/02/'> Feb </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2023/'> 2023 </a> <span class='post-count' dir='ltr'>(14)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2023/12/'> Dec </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2023/11/'> Nov </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2023/10/'> Oct </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2023/09/'> Sep </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2023/08/'> Aug </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2023/04/'> Apr </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2022/'> 2022 </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2022/02/'> Feb </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2021/'> 2021 </a> <span class='post-count' dir='ltr'>(3)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2021/06/'> Jun </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2021/04/'> Apr </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2021/03/'> Mar </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2020/'> 2020 </a> <span class='post-count' dir='ltr'>(8)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2020/12/'> Dec </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2020/11/'> Nov </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2020/10/'> Oct </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2020/08/'> Aug </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2020/07/'> Jul </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2020/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2019/'> 2019 </a> <span class='post-count' dir='ltr'>(4)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2019/12/'> Dec </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2019/11/'> Nov </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2019/07/'> Jul </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2019/01/'> Jan </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2018/'> 2018 </a> <span class='post-count' dir='ltr'>(7)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2018/11/'> Nov </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2018/09/'> Sep </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2018/07/'> Jul </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2018/06/'> Jun </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2018/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2018/02/'> Feb </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/'> 2017 </a> <span class='post-count' dir='ltr'>(17)</span> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/12/'> Dec </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2017/12/testing-on-toilet-only-verify-state.html'> Testing on the Toilet: Only Verify State-Changing ... </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/11/'> Nov </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2017/11/obsessed-with-primitives.html'> Code Health: Obsessed With Primitives? </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/10/'> Oct </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html'> Code Health: IdentifierNamingPostForWorldWideWebBlog </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/09/'> Sep </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2017/09/code-health-providing-context-with.html'> Code Health: Providing Context with Commit Message... </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/08/'> Aug </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2017/08/code-health-eliminate-yagni-smells.html'> Code Health: Eliminate YAGNI Smells </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/07/'> Jul </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2017/07/code-health-to-comment-or-not-to-comment.html'> Code Health: To Comment or Not to Comment? </a> </li> <li> <a href='https://testing.googleblog.com/2017/07/evolution-of-gtac-and-engineering.html'> Evolution of GTAC and Engineering Productivity </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/06/'> Jun </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2017/06/code-health-too-many-comments-on-your.html'> Code Health: Too Many Comments on Your Code Reviews? </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/05/'> May </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/04/'> Apr </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/02/'> Feb </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/01/'> Jan </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2016/'> 2016 </a> <span class='post-count' dir='ltr'>(15)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2016/12/'> Dec </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2016/11/'> Nov </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2016/10/'> Oct </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2016/09/'> Sep </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2016/08/'> Aug </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2016/06/'> Jun </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2016/05/'> May </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2016/04/'> Apr </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2016/03/'> Mar </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2016/02/'> Feb </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2015/'> 2015 </a> <span class='post-count' dir='ltr'>(14)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2015/12/'> Dec </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2015/11/'> Nov </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2015/10/'> Oct </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2015/08/'> Aug </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2015/06/'> Jun </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2015/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2015/04/'> Apr </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2015/03/'> Mar </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2015/02/'> Feb </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2015/01/'> Jan </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/'> 2014 </a> <span class='post-count' dir='ltr'>(24)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/12/'> Dec </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/11/'> Nov </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/10/'> Oct </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/09/'> Sep </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/08/'> Aug </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/07/'> Jul </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/06/'> Jun </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/04/'> Apr </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/03/'> Mar </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/02/'> Feb </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2014/01/'> Jan </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2013/'> 2013 </a> <span class='post-count' dir='ltr'>(16)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2013/12/'> Dec </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2013/11/'> Nov </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2013/10/'> Oct </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2013/08/'> Aug </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2013/07/'> Jul </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2013/06/'> Jun </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2013/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2013/04/'> Apr </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2013/03/'> Mar </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2013/01/'> Jan </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2012/'> 2012 </a> <span class='post-count' dir='ltr'>(11)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2012/12/'> Dec </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2012/11/'> Nov </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2012/10/'> Oct </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2012/09/'> Sep </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2012/08/'> Aug </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/'> 2011 </a> <span class='post-count' dir='ltr'>(39)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/11/'> Nov </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/10/'> Oct </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/09/'> Sep </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/08/'> Aug </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/07/'> Jul </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/06/'> Jun </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/05/'> May </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/04/'> Apr </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/03/'> Mar </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/02/'> Feb </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2011/01/'> Jan </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/'> 2010 </a> <span class='post-count' dir='ltr'>(37)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/12/'> Dec </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/11/'> Nov </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/10/'> Oct </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/09/'> Sep </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/08/'> Aug </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/07/'> Jul </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/06/'> Jun </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/04/'> Apr </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/03/'> Mar </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/02/'> Feb </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2010/01/'> Jan </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/'> 2009 </a> <span class='post-count' dir='ltr'>(54)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/12/'> Dec </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/11/'> Nov </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/10/'> Oct </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/09/'> Sep </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/08/'> Aug </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/07/'> Jul </a> <span class='post-count' dir='ltr'>(15)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/06/'> Jun </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/05/'> May </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/04/'> Apr </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/02/'> Feb </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2009/01/'> Jan </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/'> 2008 </a> <span class='post-count' dir='ltr'>(75)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/12/'> Dec </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/11/'> Nov </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/10/'> Oct </a> <span class='post-count' dir='ltr'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/09/'> Sep </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/08/'> Aug </a> <span class='post-count' dir='ltr'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/07/'> Jul </a> <span class='post-count' dir='ltr'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/06/'> Jun </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/05/'> May </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/04/'> Apr </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/03/'> Mar </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/02/'> Feb </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2008/01/'> Jan </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/'> 2007 </a> <span class='post-count' dir='ltr'>(41)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/10/'> Oct </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/09/'> Sep </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/08/'> Aug </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/07/'> Jul </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/06/'> Jun </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/04/'> Apr </a> <span class='post-count' dir='ltr'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/03/'> Mar </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/02/'> Feb </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/01/'> Jan </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> </div> </div> <div class='clear'></div> </div> </div><div class='widget HTML' data-version='1' id='HTML6'> <div class='widget-content'> <a href="http://googletesting.blogspot.com/atom.xml"> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAihJREFUeNrsWa9Pw0AU7viRMDFRBAkzJDMIBIhJJhCzk7NILIqMv4AEhdz+BCY3OYssAlGBoAJREpZwAlHEBO8lr8nSvNeVbu1dyX3JlzTrXfa+u/e9d7c5joWFhYVO1Fa8PwH2gK6m+BRwAvSlAdsrgr8E1jUuMH73GTAEzrkBWymTewZlihhLmgDXIAFuHgGVQOUF7OSYM1p6PgTuA1vAZlUEvAnPdapcMY0VICECekQ0XRfYrqoHsAGNgXfAoMomRiFDEhOZkkL3S88hMaB2LwXp0bj+ps2edpToZpjfoIDQtBeU+xjoDzP2G/gCPKZ5f8WsCAFJoJgOCcFdWSTeL9YQMSvTA1h9BkI5jaiXhLpSCL/8mVZY0UpyJ9ZdOkniu1dmJ96BpzQu9w6s28gcOq9j6pwLdR8/36NK5CQKwJSMrb2MhhSglBpt4UjsrdsnNu0B3J0HCozbCc4TjyY2srEgos/4RQljCzNxl4ireQD8FOq+T+W0mTB2g7njhlR+Sy2jsXFvU658U8YTbeaGpdIu7mWkEAq5ZtIjIhFZdtfX7QHckSvB2B6zC3VdAkZk0kAQwaXTk/CzTXK3wjIExCs6ZJpTnE4uY1KV+KzFzA3KTiFPENHJkOPcsfpLhwe4btoSuvUqAR+6TOxlCE6ZfKUsJLgsqGW8OpqAGx2X+sLxrwUog+JUeQRMDBIwyXOcnlPtPnL0/UsT/8LnOxYWFhZG4leAAQAAQHEaYuzHbAAAAABJRU5ErkJggg==" class="sidebar-icon" /> <h2>Feed</h2> </a> </div> <div class='clear'></div> </div></div> <div class='section' id='sidebar-bottom'><div class='widget HTML' data-version='1' id='HTML9'> <div class='widget-content'> <a href='http://cloud.feedly.com/#subscription%2Ffeed%2Fhttp%3A%2F%2Fgoogletesting.blogspot.com%2Ffeeds%2Fposts%2Fdefault' target='blank'><img id="feedlyFollow" src="https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vz4rHavTpGCQ2YCCEwMKBFzWvn33T8lcjwwXJ-VNs4INPE1Tk__BZYuzhYUXwAdzgBvDhO0Inl_Lpf2FHAhcOfjegUph0l553N2sVXyfT9yR75wQ5MPM_aBmUE1nChEC2g7rjkfpBdAMwWzNC2Upg=s0-d" alt="follow us in feedly" width="66" height="20"></a> <div class="share followgooglewrapper"> <button data-href="https://twitter.com/intent/follow?original_referer=http://googletesting.blogspot.com/&screen_name=googletesting" onclick='sharingPopup(this);' id='twitter-share'><span class="twitter-follow">Follow @googletesting</span></button> <script> function sharingPopup (button) { var url = button.getAttribute("data-href"); window.open( url,'popUpWindow','height=500,width=500,left=10,top=10,resizable=yes,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no,status=yes'); } </script> </div> </div> <div class='clear'></div> </div></div> </div> </div> <div style='clear:both;'></div> </div> <!-- Footer --> <div class='google-footer-outer loading'> <div id='google-footer'> <a href='//www.google.com/'> <img class='google-logo-dark' height='36' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALgAAABICAYAAABFoT/eAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAACLVJREFUeNrsXd+L20YQ3vOprdLqiMXFXE2qB7dcwEcTSB7ykIc+9A/PQx/yEMq1TWhNuYIpJriNr7XpmZ5IxFEvmW2EKs3Ornb1w50PxIFP0kiz387OzM6uhGAwGAxGP3Ho+f7x7ri1O7LdccPqZjSNA4dEHsLfaHcEFedJom93x9Xu2OyOFTcBo6sED3fHZHeMEELrkAHJF0B8Rr+gDFsZ5n0luLTQ95AXs4W06D/tjpR50xtM4CjD0y48YGB4rnyZxNOzyA7zBHr+nLnDaJLg0mo/ALekCasg3Z4XbM0ZdTEgnDPeHY8bIne+Qz2GvwyGNwsuyT218KWvIIBMcwGpLiipcolecjMxfBDchNyS1EvxLiOSIecp31q6IJ/C3yrIrMqMm4jhg+AxkdwbIO3aUO4KjqqMjCT3uaazMBhWBJfuxH3CtRfiXf66DhSRZWbmlMnNaILgZxrXJQO/eO3wORZwvwm4JUxuhheCjzVBYAbW1ces45YDSoZrFNOEE835M8FT6oyeEnws8Fz3QnBxFKPHBMem4GU+m6fPGb0leCTwWcM5B36MPgeZI01gudyDdw3hPeXfo8L/rmCUWnuMMdqUL2WqWeRbhf+twfVsO7YagZGNC79fw7OthEVtkiJ4jJzTd3KPwf3CRqhhiTu23AP5sl0/0xiwISQXpNwLIJK87mHF+U8ddzzdmgKlGzlPYjyxGJQouIhNT4k9AqWEFkqfguIvagTWbcq3KW1WE3xS3m8NtA9WS451xofwjKT5kkDoK/b6mDk5FfXr1lWDL4BofZEv2/SRsK/EHGlGdBdu8QNRb8HMCFwt7Yy3DDI/QP7fx5z3VLhdlJEIs4rKNuXXJXdxZPdB7kfCzWqwCO4V1LHgLjInX3tQ1KzCR52Cz+vDj1dydeRuS74rcvs2Pi6fT5H8OaaUQPQPYcWwRSGXyhhscn5dpAnEFMkuEZetbfkTAnlSuH4DxisE+aMGeJAQ3lFl7C4LJE6QWCaCd583ORQ1jYAwjFctal7nOs2ZZvicwvlZx+RHGrcoAwKUVX8uwcc/9TT65INeDOr5shL9LDRB6QTeIy3zwfdh3WOi6axLCEhSjXU7F3h6LqggUtvyJxpynwu8tDkD98fXApOxRj8zoZ9MnGveYVIVZKaGrkBXCY65BCYNN9NkjpKOyQ81Q79JgdxS+Jn3SDTEXRI7SWzaiSTB32oI3nU3BvMfM0urhOVYgwKhuiAfc4tM07wXwm1ZRoQYSl2NUwiu01fEAHVcpixd745FvVz4dzUUc0o8rwoLy8ZSwU6CyFx1RP5II9+1bFPEFs9HWbNLiimDXE+vCm7u1CS47cofzD3aEhVY57mxRo5zlqdt+RFC1JUH2S7bcVXg4liTMakaBZZVxiTICRoivcn1sEUBlk24JmaC6kxUbYmWoqvyfck2xZGGnDFYa9MMzkYQ1ijkCX6qidybrgePiQ0QIQqoi6qRLeqQfIoRsEHaQJLBdHOnLGetSdm/IPcymJuS1PAnbQPH0MOw/39C1vL11DiLOqIsbDI8QcHvGiLnySi2qUXBicaqUSxN5LEB0g7Jt3ENXJLPJ5S1tnaZBoWbpRqrmjRE7qHmpSmNHdQcYrEUadoh+TbBnc9ri7iycI1kzPeNcLDIvbiqXpez9Tmdq6zGREPuzECBoxrPMiI2WtvyNwhJba2wy3JZ6ky5dD1lSvmZS3e4SPA1wcf1VTFHKX+cGwZzdUYcqpvUtvwrD/InDttVlyZeAKlNN5MKbAiurHhKIPlUuJvlTCCiDjSKSCsUmCFWbGLZwCESfK07JB8LvMYWVtw0D00JEHV8Mq2HkqPbE0oHLvvK2g0o8ETg+4cfwTlZDT9JDoWygu4uQQE/ivIvtcnfPkaCqhiupz7jWOAzqL/vjtcdkv9G4MVMt+EaylfuImiPAXEUjRF3pjjaHiPPZ6If9TGGAO4ZY0am6jOCb+DQ+ZCqLkIpOIPrdNfIjnFPY6nyFut7TS/fanrziOBOKMupKw94WaLMtuVnSFt9CPrWWdJE6PeltCX432DEBoh+5Dv8RRhdis8YAv9uyq4/JAwtlEApgBe9Cw9xDD3tdk4Jn0MDfiHwPHcRPxBePCMER3GuIx7kGlv9fkZ4V9lolx2Uv4X7hEj7qJ3LDoAMGbTRMRibu4L2xQ8bgt8AyU+Q+x7nYrvDnH4iuO5LxKsYwPVbkPMvKF9Zky9wXzRfVWizi62r9X5VHf55h+WHhDjGBZ4WRhyTr6z5SlCoLMxLSpBZFsQ9F80uQFbF/6aFWi+Ev51vzzsuX+msyzuQXXjUz8zEBy+zpq9yweXAoxJW4JbYrDS6gYDqGHxPl+TKeiBfxj9/EBIElPYeOA4y8/qRQfknjvSzgRgtq0Pw/M1eQeMdOSb2Bnrhr6Led+1vcp2x7oTFHMnedFW+Ivlty062BUt74oHgSj+vHepnhunn0JJAMtBZgDI/qmGtMujRv8DDpo47zBJ8UtPOuAR/7rKn8t9AJ0tBdmBAmJ/Fu71yxp4I3qh+DhyRqbi5Y1ShVPlSb8X7bRNcfgZFl+WRGYo7uecrWq1r8X5bhmzP5OdlDwsGRm1suSxkg5rYm7ConyGQ3Zl+DgSD8V/kPwrWBMG9YcBtyShBnTLdTiHgttw7qAW7cqh/ZnmPKr/6ignOaKsdyxbsToT5UkPsW00bJjijDXficcX/JsLs6w2BwGtherdckH3w/kNXRPVI0OqJQoHX42/66IMfMj/2huRjxIidgKV/W0JS+bsstDoTeAHcrI8E5zTh/sDkqxL5rZup55/3USlswfcHf4IrQplVDgW9XFlOqnwr6pVPMMEZTuC60EttvdzbLbaZ4PsFVa3nohhO+vW+yn/ZB2fUhpysmQrzBcTSai9EszuZMcEZ1lCFVrp9zGXhm69iLyY4oxFIa178lPe12I/P2DAYDAaDwWAwGAwGg8FgMBgMBoPBYDD2Cf8IMADDRGoQTe+E9AAAAABJRU5ErkJggg==' style='margin-top: -16px;' width='92'/> </a> <ul> <li> <a href='//www.google.com/'> Google </a> </li> <li> <a href='//www.google.com/policies/privacy/'> Privacy </a> </li> <li> <a href='//www.google.com/policies/terms/'> Terms </a> </li> </ul> </div> </div> <script type='text/javascript'> //<![CDATA[ // Social sharing popups. var postEl = document.getElementsByClassName('social-wrapper'); var postCount = postEl.length; for(i=0; i<postCount;i++){ postEl[i].addEventListener("click", function(event){ var postUrl = this.getAttribute("data-href"); window.open( postUrl,'popUpWindow','height=500,width=500,left=10,top=10,resizable=yes,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no,status=yes'); });} //]]> </script> <script type='text/javascript'> //<![CDATA[ var BreakpointHandler = function() { this.initted = false; this.isHomePage = false; this.isMobile = false; }; BreakpointHandler.prototype.finalizeSummary = function(summaryHtml, lastNode) { // Use $.trim for IE8 compatibility summaryHtml = $.trim(summaryHtml).replace(/(<br>|\s)+$/,''); if (lastNode.nodeType == 3) { var lastChar = summaryHtml.slice(-1); if (!lastChar.match(/[.”"?]/)) { if (!lastChar.match(/[A-Za-z]/)) { summaryHtml = summaryHtml.slice(0, -1); } summaryHtml += ' ...'; } } else if (lastNode.nodeType == 1 && (lastNode.nodeName == 'I' || lastNode.nodeName == 'A')) { summaryHtml += ' ...'; } return summaryHtml; }; BreakpointHandler.prototype.generateSummaryFromContent = function(content, numWords) { var seenWords = 0; var summaryHtml = ''; for (var i=0; i < content.childNodes.length; i++) { var node = content.childNodes[i]; var nodeText; if (node.nodeType == 1) { if (node.hasAttribute('data-about-pullquote')) { continue; } nodeText = node.textContent; if (nodeText === undefined) { // innerText for IE8 nodeText = node.innerText; } if (node.nodeName == 'DIV' || node.nodeName == 'B') { // Don't end early if we haven't seen enough words. if (seenWords < 10) { continue; } if (i > 0) { summaryHtml = this.finalizeSummary(summaryHtml, content.childNodes[i-1]); } break; } summaryHtml += node.outerHTML; } else if (node.nodeType == 3) { nodeText = node.nodeValue; summaryHtml += nodeText + ' '; } var words = nodeText.match(/\S+\s*/g); if (!words) { continue; } var remain = numWords - seenWords; if (words.length >= remain) { summaryHtml = this.finalizeSummary(summaryHtml, node); break; } seenWords += words.length; } return summaryHtml; }; BreakpointHandler.prototype.detect = function() { var match, pl = /\+/g, search = /([^&=]+)=?([^&]*)/g, decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }, query = window.location.search.substring(1); var urlParams = {}; while (match = search.exec(query)) urlParams[decode(match[1])] = decode(match[2]); this.isListPage = $('html').hasClass('list-page'); this.isMobile = urlParams['m'] === '1'; this.isHomePage = window.location.pathname == '/'; }; BreakpointHandler.prototype.initContent = function() { var self = this; $('.post').each(function(index) { var body = $(this).children('.post-body')[0]; var content = $(body).children('.post-content')[0]; $(content).addClass('post-original'); var data = $(content).children('script').html(); data = self.rewriteForSSL(data); // If exists, extract specified editor's preview. var match = data.match(/([\s\S]+?)<div data-is-preview.+?>([\s\S]+)<\/div>/m); if (match) { data = match[1]; } // Prevent big images from loading when they aren't needed. // This must be done as a pre-injection step, since image loading can't be // canceled once embedded into the DOM. if (self.isListPage && self.isMobile) { data = data.replace(/<(img|iframe) .+?>/g, ''); } // Insert template to be rendered as nodes. content.innerHTML = data; if (self.isListPage) { var summary = document.createElement('div'); $(summary).addClass('post-content'); $(summary).addClass('post-summary'); body.insertBefore(summary, content); if (match) { // Use provided summary. summary.innerHTML = match[2]; } else { // Generate a summary. // Summary generation relies on DOM, so it must occur after content is // inserted into the page. summary.innerHTML = self.generateSummaryFromContent(content, 30); } // Add read more link to summary. var titleAnchor = $(this).find('.title a')[0]; var link = titleAnchor.cloneNode(true); link.innerHTML = 'Read More'; $(link).addClass('read-more'); summary.appendChild(link); } }); // Firefox does not allow for proper styling of BR. if (navigator.userAgent.indexOf('Firefox') > -1) { $('.post-content br').replaceWith('<span class="space"></span>'); } $('.loading').removeClass('loading'); }; BreakpointHandler.prototype.process = function() { if (!this.initted) { var makeInsecureImageRegex = function(hosts) { var whitelist = hosts.join('|').replace(/\./g,'\\.'); // Normal image tags, plus input images (yes, this is possible!) return new RegExp('(<(img|input)[^>]+?src=("|\'))http:\/\/(' + whitelist +')', 'g'); }; this.sslImageRegex = makeInsecureImageRegex(BreakpointHandler.KNOWN_HTTPS_HOSTS); this.sslImageCurrentDomainRegex = makeInsecureImageRegex([window.location.hostname]); this.detect(); this.initContent(); this.initted = true; } }; BreakpointHandler.KNOWN_HTTPS_HOSTS = [ "www.google.org", "www.google.com", "services.google.com", "blogger.com", "draft.blogger.com", "www.blogger.com", "photos1.blogger.com", "photos2.blogger.com", "photos3.blogger.com", "blogblog.com", "img1.blogblog.com", "img2.blogblog.com", "www.blogblog.com", "www1.blogblog.com", "www2.blogblog.com", "0.bp.blogspot.com", "1.bp.blogspot.com", "2.bp.blogspot.com", "3.bp.blogspot.com", "4.bp.blogspot.com", "lh3.googleusercontent.com", "lh4.googleusercontent.com", "lh5.googleusercontent.com", "lh6.googleusercontent.com", "themes.googleusercontent.com", ]; BreakpointHandler.prototype.rewriteForSSL = function(html) { // Handle HTTP -> HTTPS source replacement of images, movies, and other embedded content. return html.replace(this.sslImageRegex, '$1https://$4') .replace(this.sslImageCurrentDomainRegex, '$1//$4') .replace(/(<(embed|iframe)[^>]+?src=("|'))http:\/\/([^"']*?(youtube|picasaweb\.google)\.com)/g, '$1https://$4') // Slideshow SWF takes a image host, so we need to rewrite that parameter. .replace(/(<embed[^>]+?feed=http(?=[^s]))/g, '$1s'); }; $(document).ready(function() { var handler = new BreakpointHandler(); handler.process(); // Top-level navigation. $(".BlogArchive .tab").click(function(ev) { ev.preventDefault(); $(this).parent().toggleClass('active'); $(this).siblings().slideToggle(300); }); $(".Label .tab").click(function(ev) { ev.preventDefault(); $(this).parent().toggleClass('active'); $(this).siblings().slideToggle(300); }); // Blog archive year expansion. $('.BlogArchive .intervalToggle').click(function(ev) { ev.preventDefault(); if ($(this).parent().hasClass('collapsed')) { $(this).parent().removeClass('collapsed'); $(this).parent().addClass('expanded'); } else { $(this).parent().removeClass('expanded'); $(this).parent().addClass('collapsed'); } }); // Reverse order of months. $('.BlogArchive .intervalToggle + div').each(function(_, items) { var year = $(this); year.children().each(function(_, month) { year.prepend(month); }); }); // Set anchors to open in new tab. $('.post-content img').parent().each(function(_, node) { if (node.nodeName == 'A') { $(this).attr('target', '_blank'); } }); // Process search requests. $('.searchBox input').on("keypress", function(ev) { if (ev.which == 13) { window.location.href = 'https://www.google.com/search?q=site%3A' + window.location.hostname + '%20' + encodeURIComponent ($(this).val()); } }); }); (function($, window) { var archiveButton = $($('#sidebar .widget.BlogArchive h2')[0]); var folderIcon = $('#sidebar .widget.BlogArchive h2::after'); var archivePanel = $('#BlogArchive1'); archiveButton.click(function(e) { if (archivePanel.hasClass('archive-open')) { // It's open, so now we close it archivePanel.removeClass('archive-open'); archivePanel.addClass('archive-closed'); archiveButton.removeClass('archive-open'); archiveButton.addClass('archive-closed'); archivePanel.css('height', '60px'); } else { // It's closed, so open it archivePanel.removeClass('archive-closed'); archivePanel.addClass('archive-open'); archiveButton.removeClass('archive-closed'); archiveButton.addClass('archive-open'); archivePanel.css('height', 'auto'); folderIcon.css('content', 'https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggkDzi8QVSua_XxLOnfxWE_8nQc1MAhRPBxJej91JW2ZBbKvb2TjaNf66ZoTqCrBivwRr-TLJYxFm2ZAiMd-zfbJ0TjblXGvUszWFbdRncNOL7jseiJCL9uQoqN8BM8FpesdSw/s1600/keyboard_arrow_up_grey600_24dp.png'); } }); })($, window); (function ($, window, devsite) { devsite.devsite = {}; devsite.expandLeftNav = devsite.expandLeftNav || {}; devsite.expandLeftNav.ANALYTICS_LABEL_ = 'Hamburger menu'; devsite.expandLeftNav.ANALYTICS_ACTION_OPEN_ = 'Open'; devsite.expandLeftNav.ANALYTICS_ACTION_CLOSE_ = 'Close'; devsite.expandLeftNav.lastState_ = 0; devsite.expandLeftNav.chekovEnabled_ = false; devsite.expandLeftNav.init = function () { devsite.expandLeftNav.chekovEnabled_ = true; var navElement; if (devsite.expandLeftNav.chekovEnabled_) { navElement = $('.devsite-nav-responsive'); } else { navElement = $('.devsite-section-nav-responsive'); } this.drawerWidth = parseInt(navElement.css('width')); navElement.css({ 'left': -(this.drawerWidth) }); var expandButton = $('.devsite-expand-section-nav'); expandButton.click(function () { devsite.expandLeftNav.handleNavigationOpened(); }); navElement.find('.devsite-nav-responsive-forward').click( devsite.expandLeftNav.openPanel); navElement.find('.devsite-nav-responsive-back').click( devsite.expandLeftNav.closePanel); if ($('.devsite-nav-responsive-tabs-panel + ' + '.devsite-nav-responsive-sidebar-panel').length) { devsite.expandLeftNav.openPanel(); } }; devsite.expandLeftNav.handleNavigationOpened = function (opt_noAnimate) { var mask; if (devsite.expandLeftNav.chekovEnabled_) { var nav = $('.devsite-nav-responsive'); if (opt_noAnimate) { nav.addClass('devsite-nav-responsive-no-animate'); mask = devsite.devsite.showSiteMask(0); } else { mask = devsite.devsite.showSiteMask(); } nav.addClass('devsite-nav-responsive-open'); } else { devsite.expandLeftNav.lastState_ = devsite.sticky.currentState; devsite.sticky.setState(devsite.sticky.state.COLLAPSED_HEADER); var headerHeight = devsite.sticky.getHeaderHeight() - devsite.sticky.desiredMargin; var drawerHeight = $(window).height() - headerHeight; mask = devsite.devsite.showArticleMask(); $('.devsite-section-nav-responsive').css({ 'height': drawerHeight, 'left': '0', 'top': headerHeight, 'visibility': 'visible' }).focus(); } $(mask).click(devsite.expandLeftNav.handleNavigationClosed); $(document).on('keydown.escape', function (e) { if (e.keyCode == $.ui.keyCode.ESCAPE) { devsite.expandLeftNav.handleNavigationClosed(); $(document).off('keydown.escape'); } }); }; devsite.expandLeftNav.getScrollTop = function () { return $(window).scrollTop(); }; devsite.expandLeftNav.handleNavigationClosed = function () { var nav; if (devsite.expandLeftNav.chekovEnabled_) { nav = $('.devsite-nav-responsive'); devsite.devsite.hideSiteMask(); nav.removeClass('devsite-nav-responsive-open ' + 'devsite-nav-responsive-no-animate'); } else { nav = $('.devsite-section-nav-responsive'); devsite.devsite.hideArticleMask(); devsite.sticky.setState(devsite.expandLeftNav.lastState_); nav .css('left', -(devsite.expandLeftNav.drawerWidth)) .one('transitionend', function () { nav.css('visibility', 'hidden'); }); } nav.scrollTop(0); }; devsite.expandLeftNav.openPanel = function () { var parentPanel = $('.devsite-nav-responsive-tabs-panel'); var childPanel = $('.devsite-nav-responsive-sidebar-panel'); childPanel.show(); parentPanel .addClass('devsite-nav-responsive-transition') .addClass('devsite-nav-responsive-transform') .one('transitionend', function () { childPanel .removeClass('devsite-nav-responsive-transition') .removeClass('devsite-nav-responsive-transform'); parentPanel.hide(); }); setTimeout(function () { childPanel .addClass('devsite-nav-responsive-transition') .addClass('devsite-nav-responsive-transform'); }, 1); }; devsite.expandLeftNav.closePanel = function () { var parentPanel = $('.devsite-nav-responsive-tabs-panel'); var childPanel = $('.devsite-nav-responsive-sidebar-panel'); childPanel .removeClass('devsite-nav-responsive-transition') .addClass('devsite-nav-responsive-transform'); parentPanel .show() .removeClass('devsite-nav-responsive-transition') .addClass('devsite-nav-responsive-transform'); setTimeout(function () { parentPanel .addClass('devsite-nav-responsive-transition') .removeClass('devsite-nav-responsive-transform'); childPanel .addClass('devsite-nav-responsive-transition') .removeClass('devsite-nav-responsive-transform') .one('transitionend', function () { childPanel.hide(); parentPanel.removeClass('devsite-nav-responsive-transition'); }); }, 1); }; devsite.expandLeftNav.FADE_SLOW_ = 'slow'; devsite.expandLeftNav.FADE_FAST_ = 'fast'; devsite.expandLeftNav.SITE_MASK_CSS_ = '.devsite-site-mask'; devsite.devsite.showSiteMask = function(opt_animate) { if (opt_animate === undefined) { opt_animate = devsite.expandLeftNav.FADE_SLOW_; } devsite.devsite.setMouseScrollingEnabled(false); return devsite.devsite.setMask_(devsite.expandLeftNav.SITE_MASK_CSS_, false, opt_animate); }; devsite.devsite.hideSiteMask = function(opt_animate) { if (opt_animate === undefined) { opt_animate = devsite.expandLeftNav.FADE_FAST_; } devsite.devsite.setMouseScrollingEnabled(true); return devsite.devsite.setMask_(devsite.expandLeftNav.SITE_MASK_CSS_, true, opt_animate); }; devsite.devsite.showArticleMask = function() { devsite.devsite.setMouseScrollingEnabled(false); return devsite.devsite.setMask_('.devsite-article-mask', false, devsite.expandLeftNav.FADE_SLOW_); }; devsite.devsite.hideArticleMask = function() { devsite.devsite.setMouseScrollingEnabled(true); return devsite.devsite.setMask_('.devsite-article-mask', true, devsite.expandLeftNav.FADE_FAST_); }; devsite.devsite.setMask_ = function(className, out, opt_fadeTime) { var query = $(className); if (opt_fadeTime === 0) { out ? query.hide() : query.show(); } else { out ? query.fadeOut(opt_fadeTime) : query.fadeIn(opt_fadeTime); } return $(className)[0]; }; devsite.devsite.setMouseScrollingEnabled = function(trueOrFalse) { if (trueOrFalse == true) { $('html, body').css({ 'overflow': '' }); } else { $('html, body').css({ 'overflow': 'hidden' }); } }; })($, window, devsite = {}); if (window.jQuery) { $(document).ready(function () { if (window.devsite) { devsite.expandLeftNav.init(); } }); } //]]> </script> <style> .widget ul{ line-height: 1.6 !important; } #sidebar ul li a{ color:black; line-height: 20px; } #sidebar ul li a:hover{ color:#4184F3; } </style> <script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/984859869-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AOuZoY4_7Y9Thp5Z7zEApVgN0HluZ3205g:1732438424898';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d15045980','//testing.googleblog.com/2017/','15045980'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '15045980', 'title': 'Google Testing Blog', 'url': 'https://testing.googleblog.com/2017/', 'canonicalUrl': 'https://testing.googleblog.com/2017/', 'homepageUrl': 'https://testing.googleblog.com/', 'searchUrl': 'https://testing.googleblog.com/search', 'canonicalHomepageUrl': 'https://testing.googleblog.com/', 'blogspotFaviconUrl': 'https://testing.googleblog.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': true, 'httpsEnabled': true, 'enabledCommentProfileImages': true, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': 'G-838ZCPQWM6', 'analytics4': true, 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Google Testing Blog - Atom\x22 href\x3d\x22https://testing.googleblog.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22Google Testing Blog - RSS\x22 href\x3d\x22https://testing.googleblog.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Google Testing Blog - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/15045980/posts/default\x22 /\x3e\n', 'meTag': '', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': false, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/d78375fb222d99b3', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': 'Get link', 'key': 'link', 'shareMessage': 'Get link', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': 'Share to Facebook', 'target': 'facebook'}, {'name': 'BlogThis!', 'key': 'blogThis', 'shareMessage': 'BlogThis!', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': 'Share to X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': 'Share to Pinterest', 'target': 'pinterest'}, {'name': 'Email', 'key': 'email', 'shareMessage': 'Email', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27en\x27};\x3c/script\x3e'}, 'hasCustomJumpLinkMessage': false, 'jumpLinkMessage': 'Read more', 'pageType': 'archive', 'pageName': '2017', 'pageTitle': 'Google Testing Blog: 2017'}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': 'Edit', 'linkCopiedToClipboard': 'Link copied to clipboard!', 'ok': 'Ok', 'postLink': 'Post Link'}}, {'name': 'template', 'data': {'name': 'custom', 'localizedName': 'Custom', 'isResponsive': false, 'isAlternateRendering': false, 'isCustom': true}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': 'Google Testing Blog', 'description': '', 'url': 'https://testing.googleblog.com/2017/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': true, 'isLabelSearch': false, 'archive': {'year': 2017, 'rangeMessage': 'Showing posts from 2017'}}}]); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false, 'lightboxEnabled': true, 'lightboxModuleUrl': 'https://www.blogger.com/static/v1/jsbin/2646514562-lbx.js', 'lightboxCssUrl': 'https://www.blogger.com/static/v1/v-css/1964470060-lightbox_bundle.css'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML8', 'sidebar-top', document.getElementById('HTML8'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_LabelView', new _WidgetInfo('Label1', 'sidebar', document.getElementById('Label1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive1', 'sidebar', document.getElementById('BlogArchive1'), {'languageDirection': 'ltr', 'loadingMessage': 'Loading\x26hellip;'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML6', 'sidebar', document.getElementById('HTML6'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML9', 'sidebar-bottom', document.getElementById('HTML9'), {}, 'displayModeFull')); </script> </body> </html>