CINXE.COM

Google Testing Blog: 2007

<!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: 2007 </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/2007/' 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/2007/' 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/2007/' 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&amp;zx=4c9c4e02-9554-497d-a918-34dbbf42a9c2' media='none' onload='if(media!=&#39;all&#39;)media=&#39;all&#39;' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=15045980&amp;zx=4c9c4e02-9554-497d-a918-34dbbf42a9c2' 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='7547529411853240034' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/10/tott-avoiding-friend-twister-in-c.html' itemprop='url' title='TotT: Avoiding friend Twister in C++'> TotT: Avoiding friend Twister in C++ </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Tuesday, October 30, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <p>(resuming our testing on the toilet posts...)<br /></p><p>In a <a href="http://googletesting.blogspot.com/2007/06/tott-extracting-methods-to-simplify.html">previous episode</a>, we <b><span style="color: rgb(128, 0, 0);">extracted methods to simplify testing</span></b> in Python. But if these extracted methods make the most sense as private class members, how can you write your production code so it doesn't depend on your test code? In Python this is easy; but in C++, testing private members requires more <b> <code><span style="color: rgb(128, 0, 0);">friend</span></code></b> contortions than a game of Twister&#174;. </p> <blockquote style="background: rgb(230, 245, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-size: small;"> <pre><br />// my_package/dashboard.h<br /><b>class</b> Dashboard {<br /> <b>private:</b><br /> scoped_ptr&lt;Database&gt; database_; // instantiated in constructor<br /><br /> // Declaration of functions GetResults(), GetResultsFromCache(),<br /> // GetResultsFromDatabase(), CountPassFail()<br /><br /> <b>friend</b> class DashboardTest; // one friend declaration per test<br /> // fixture<br />};<br /><br /></pre> </blockquote> <p> You can apply the <b><span style="color: rgb(128, 0, 0);">Extract Class</span></b> and <b><span style="color: rgb(128, 0, 0);">Extract Interface</span></b> refactorings to create a new <b><span style="color: rgb(128, 0, 0);">helper class</span></b> containing the implementation. Forward declare the new interface in the <b><code>.h</code></b> of the original class, and have the original class hold a pointer to the interface. (This is similar to the Pimpl idiom.) You can distinguish between the public API and the implementation details by separating the headers into different subdirectories (<b><code>/my_package/public/</code></b> and <b><code>/my_package/</code></b> in this example): </p> <blockquote style="background: rgb(230, 245, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-size: small;"> <pre><br />// my_package/public/dashboard.h<br /><b>class</b> ResultsLog; // extracted helper interface<br /><b>class</b> Dashboard {<br /> <b>public:</b><br /> <b>explicit</b> Dashboard(ResultsLog* results) : results_(results) { }<br /> <b>private:</b><br /> scoped_ptr&lt;ResultsLog&gt; results_;<br />};<br /><br />// my_package/results_log.h<br /><b>class</b> ResultsLog {<br /> <b>public:</b><br /> // Declaration of functions GetResults(),<br /> // GetResultsFromCache(),<br /> // GetResultsFromDatabase(), CountPassFail()<br />};<br /><br />// my_package/live_results_log.h<br /><b>class</b> LiveResultsLog <b>: public</b> ResultsLog {<br /> <b>public:</b><br /> <b>explicit</b> LiveResultsLog(Database* database)<br /> : database_(database) { }<br />};<br /><br /></pre> </blockquote> <p> Now you can test <b><code>LiveResultsLog</code></b> without resorting to <b><code>friend</code></b> declarations. This also enables you to inject <b><code>MockResultsLog</code></b> instance when testing the <b><code>Dashboard</code></b> class. The functionality is still private to the original class, and the use of a helper class results in smaller classes with better-defined responsibilities. </p><p>Remember to download <a href="http://code.google.com/testing/TotT-2007-10-30.pdf">this episode</a> of Testing on the Toilet and post it in your office.</p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <p>(resuming our testing on the toilet posts...)<br /></p><p>In a <a href="http://googletesting.blogspot.com/2007/06/tott-extracting-methods-to-simplify.html">previous episode</a>, we <b><span style="color: rgb(128, 0, 0);">extracted methods to simplify testing</span></b> in Python. But if these extracted methods make the most sense as private class members, how can you write your production code so it doesn't depend on your test code? In Python this is easy; but in C++, testing private members requires more <b> <code><span style="color: rgb(128, 0, 0);">friend</span></code></b> contortions than a game of Twister&#174;. </p> <blockquote style="background: rgb(230, 245, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-size: small;"> <pre><br />// my_package/dashboard.h<br /><b>class</b> Dashboard {<br /> <b>private:</b><br /> scoped_ptr&lt;Database&gt; database_; // instantiated in constructor<br /><br /> // Declaration of functions GetResults(), GetResultsFromCache(),<br /> // GetResultsFromDatabase(), CountPassFail()<br /><br /> <b>friend</b> class DashboardTest; // one friend declaration per test<br /> // fixture<br />};<br /><br /></pre> </blockquote> <p> You can apply the <b><span style="color: rgb(128, 0, 0);">Extract Class</span></b> and <b><span style="color: rgb(128, 0, 0);">Extract Interface</span></b> refactorings to create a new <b><span style="color: rgb(128, 0, 0);">helper class</span></b> containing the implementation. Forward declare the new interface in the <b><code>.h</code></b> of the original class, and have the original class hold a pointer to the interface. (This is similar to the Pimpl idiom.) You can distinguish between the public API and the implementation details by separating the headers into different subdirectories (<b><code>/my_package/public/</code></b> and <b><code>/my_package/</code></b> in this example): </p> <blockquote style="background: rgb(230, 245, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-size: small;"> <pre><br />// my_package/public/dashboard.h<br /><b>class</b> ResultsLog; // extracted helper interface<br /><b>class</b> Dashboard {<br /> <b>public:</b><br /> <b>explicit</b> Dashboard(ResultsLog* results) : results_(results) { }<br /> <b>private:</b><br /> scoped_ptr&lt;ResultsLog&gt; results_;<br />};<br /><br />// my_package/results_log.h<br /><b>class</b> ResultsLog {<br /> <b>public:</b><br /> // Declaration of functions GetResults(),<br /> // GetResultsFromCache(),<br /> // GetResultsFromDatabase(), CountPassFail()<br />};<br /><br />// my_package/live_results_log.h<br /><b>class</b> LiveResultsLog <b>: public</b> ResultsLog {<br /> <b>public:</b><br /> <b>explicit</b> LiveResultsLog(Database* database)<br /> : database_(database) { }<br />};<br /><br /></pre> </blockquote> <p> Now you can test <b><code>LiveResultsLog</code></b> without resorting to <b><code>friend</code></b> declarations. This also enables you to inject <b><code>MockResultsLog</code></b> instance when testing the <b><code>Dashboard</code></b> class. The functionality is still private to the original class, and the use of a helper class results in smaller classes with better-defined responsibilities. </p><p>Remember to download <a href="http://code.google.com/testing/TotT-2007-10-30.pdf">this episode</a> of Testing on the Toilet and post it in your office.</p> <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:TotT: Avoiding friend Twister in C++&url=https://testing.googleblog.com/2007/10/tott-avoiding-friend-twister-in-c.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/2007/10/tott-avoiding-friend-twister-in-c.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/10/tott-avoiding-friend-twister-in-c.html#comments' style='font-weight: 500; text-decoration: underline;'>5 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/10/tott-avoiding-friend-twister-in-c.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/C%2B%2B' rel='tag'> C++ </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='8050317982710955159' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/10/automating-tests-vs-test-automation.html' itemprop='url' title='Automating tests vs. test-automation'> Automating tests vs. test-automation </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Wednesday, October 24, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span style="font-size:100%;"><span style="font-size: 100%; color: rgb(0, 0, 0); font-family: arial;">Posted by </span><span email="markusclermont@google.com" class="EP8xU" style="color: rgb(0, 0, 0); font-family: arial;">Markus <span class="blsp-spelling-error" id="SPELLING_ERROR_0">Clermont</span></span><span style="font-size: 100%; color: rgb(0, 0, 0); font-family: arial;">, Test Engineering Manager, Zurich</span><br /><br /><span style="font-family: arial;">In the last couple of years the practice of testing has undergone more than superficial changes. We have turned our art into engineering, introduced process-models, come up with best-practices, and developed tools to support our daily work and make each test engineer more productive. Some tools target test execution. They aim to automate the repetitive steps that a tester would take to exercise functions through the user interface of a system in order to verify its functionality. I am sure you have all seen tools like Selenium, <span class="blsp-spelling-error" id="SPELLING_ERROR_1">WebDriver</span>, Eggplant or other proprietary solutions, and that you learned to love them.</span><br /><br /><span style="font-family: arial;">On the downside, we observe problems when we employ these tools:</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">Scripting your manual tests this way takes far longer than just executing them manually.</span></li><li><span style="font-size:100%;">The <span class="blsp-spelling-error" id="SPELLING_ERROR_2">UI</span> is one of the least stable interfaces of any system, so we can start automating quite late in the development phase.</span></li><li><span style="font-size:100%;">Maintenance of the tests takes a significant amount of time.</span></li><li><span style="font-size:100%;">Execution is slow, and sometimes cumbersome.</span></li><li><span style="font-size:100%;">Tests become flaky.</span></li><li><span style="font-size:100%;">Tests break for the wrong reasons.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">Of course, we can argue that none of these problems is particularly bad, and the advantages of automation still outweigh the cost. This might well be true. We learned to accept some of these problems as 'the price of automation', whereas others are met by some common-sense workarounds:</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">It takes long to automate a test&#8212;Well, let's automate only tests that are important, and will be executed again and again in regression testing.</span></li><li><span style="font-size:100%;">Execution might be slow, but it is still faster than manual testing.</span></li><li><span style="font-size:100%;">Tests cannot break for the wrong reason&#8212;When they break we found a bug.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">In the rest of this post I'd like to summarize some experiences I had when I tried to overcome these problems, not by working around them, but by eliminating their causes.</span><br /><br /><span style="font-family: arial;">Most of these problems are rooted in the fact that we are just automating manual tests. By doing so we are not taking into account whether the added computational power, access to different interfaces, and faster execution speed should make us change the way we test systems.</span><br /><br /><span style="font-family: arial;">Considering the fact that a system exposes different interfaces to the environment&#8212;e.g., the user-interface, an interface between front-end and back-end, an interface to a data-store, and interfaces to other systems&#8212;it is obvious that we need to look at each and every interface and test it. More than that we should not only take each interface into account but also avoid testing the functionality in too many different places.</span><br /><br /><span style="font-family: arial;">Let me introduce the example of a store-administration system which allows you to add items to the store, see the current inventory, and remove items. One straightforward manual test case for adding an item would be to go to the 'Add' dialogue, enter a new item with quantity 1, and then go to the 'Display' dialogue to check that it is there. To automate this test case you would instrument exactly all the steps through the user-interface.</span><br /><br /><span style="font-family: arial;">Probably most of the problems I listed above will apply. One way to avoid them in the first place would have been to figure out how this system looks inside.</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">Is there a database? If so, the verification should probably not be performed against the <span class="blsp-spelling-error" id="SPELLING_ERROR_3">UI</span> but against the database.</span></li><li><span style="font-size:100%;">Do we need to interface with a supplier? If so, how should this interaction look?</span></li><li><span style="font-size:100%;">Is the same functionality available via an <span class="blsp-spelling-error" id="SPELLING_ERROR_4">API</span>? If so, it should be tested through the <span class="blsp-spelling-error" id="SPELLING_ERROR_5">API</span>, and the <span class="blsp-spelling-error" id="SPELLING_ERROR_6">UI</span> should just be checked to interact with the <span class="blsp-spelling-error" id="SPELLING_ERROR_7">API</span> correctly.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">This will probably yield a higher number of tests, some of them being much 'smaller' in their resource requirements and executing far faster than the full end-to-end tests. Applying these simple questions will allow us to:</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">write many more tests through the <span class="blsp-spelling-error" id="SPELLING_ERROR_8">API</span>, e.g., to cover many boundary conditions,</span></li><li><span style="font-size:100%;">execute multiple threads of tests on the same machine, giving us a chance to spot race-conditions,</span></li><li><span style="font-size:100%;">start earlier with testing the system, as we can test each interface when it becomes 'quasi-stable',</span></li><li><span style="font-size:100%;">makes maintenance of tests and debugging easier, as the tests break closer to the source of the problem,</span></li><li><span style="font-size:100%;">require fewer machine resources, and still execute in reasonable time.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">I am not advocating the total absence of <span class="blsp-spelling-error" id="SPELLING_ERROR_9">UI</span> tests here. The user interface is just another interface, and so it deserves attention too. However I do think that we are currently focusing most of our testing-efforts on the <span class="blsp-spelling-error" id="SPELLING_ERROR_10">UI</span>. The common attitude, that the <span class="blsp-spelling-error" id="SPELLING_ERROR_11">UI</span> deserves most attention because it is what the user sees, is flawed. Even a perfect <span class="blsp-spelling-error" id="SPELLING_ERROR_12">UI</span> will not satisfy a user if the underlying functionality is corrupt.</span><br /><br /><span style="font-family: arial;">Neither should we abandon our end-to-end tests. They are valuable and no system can be considered tested without them. Again, the question we need to ask ourselves is the ratio between full end-to-end tests and smaller integration tests.</span><br /><br /><span style="font-family: arial;">Unfortunately, there is no free lunch. In order to change the style of test-automation we will also need to change our approach to testing. Successful test-automation needs to:</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">start early in the development cycle,</span></li><li><span style="font-size:100%;">take the internal structure of the system into account,</span></li><li><span style="font-size:100%;">have a feedback loop to developers to influence the system-design.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">Some of these points require quite a change in the way we approach testing. They are only achievable if we work as a single team with our developers. It is crucial that there is an absolute free flow of information between the different roles in this team.</span><br /><br /><span style="font-family: arial;">In previous projects we were able to achieve this by</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">removing any spatial separation between the test engineers and the development engineers. Sitting on the next desk is probably the best way to promote information exchange,</span></li><li><span style="font-size:100%;">using the same tools and methods as the developers,</span></li><li><span style="font-size:100%;">getting involved into daily stand-ups and design-discussions.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">This helps not only in getting involved really early (there are projects where test development starts at the same time as development), but it is also a great way to give continuous feedback. Some of the items in the list call for very development-oriented test engineers, as it is easier for them to be recognized as a peer by the development teams.</span><br /><br /><span style="font-family: arial;">To summarize, I figured out that a successful automation project needs:</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">to take the internal details and exposed interface of the system under test into account,</span></li><li><span style="font-size:100%;">to have many fast tests for each interface (including the <span class="blsp-spelling-error" id="SPELLING_ERROR_13">UI</span>),</span></li><li><span style="font-size:100%;">to verify the functionality at the lowest possible level,<br /></span></li><li><span style="font-size:100%;">to have a set of end-to-end tests,</span></li><li><span style="font-size:100%;">to start at the same time as development,</span></li><li><span style="font-size:100%;">to overcome traditional boundaries between development and testing (spatial, organizational and process boundaries), and<br /></span></li><li><span style="font-size:100%;">to use the same tools as the development team.</span></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 style="font-size:100%;"><span style="font-size: 100%; color: rgb(0, 0, 0); font-family: arial;">Posted by </span><span email="markusclermont@google.com" class="EP8xU" style="color: rgb(0, 0, 0); font-family: arial;">Markus <span class="blsp-spelling-error" id="SPELLING_ERROR_0">Clermont</span></span><span style="font-size: 100%; color: rgb(0, 0, 0); font-family: arial;">, Test Engineering Manager, Zurich</span><br /><br /><span style="font-family: arial;">In the last couple of years the practice of testing has undergone more than superficial changes. We have turned our art into engineering, introduced process-models, come up with best-practices, and developed tools to support our daily work and make each test engineer more productive. Some tools target test execution. They aim to automate the repetitive steps that a tester would take to exercise functions through the user interface of a system in order to verify its functionality. I am sure you have all seen tools like Selenium, <span class="blsp-spelling-error" id="SPELLING_ERROR_1">WebDriver</span>, Eggplant or other proprietary solutions, and that you learned to love them.</span><br /><br /><span style="font-family: arial;">On the downside, we observe problems when we employ these tools:</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">Scripting your manual tests this way takes far longer than just executing them manually.</span></li><li><span style="font-size:100%;">The <span class="blsp-spelling-error" id="SPELLING_ERROR_2">UI</span> is one of the least stable interfaces of any system, so we can start automating quite late in the development phase.</span></li><li><span style="font-size:100%;">Maintenance of the tests takes a significant amount of time.</span></li><li><span style="font-size:100%;">Execution is slow, and sometimes cumbersome.</span></li><li><span style="font-size:100%;">Tests become flaky.</span></li><li><span style="font-size:100%;">Tests break for the wrong reasons.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">Of course, we can argue that none of these problems is particularly bad, and the advantages of automation still outweigh the cost. This might well be true. We learned to accept some of these problems as 'the price of automation', whereas others are met by some common-sense workarounds:</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">It takes long to automate a test&#8212;Well, let's automate only tests that are important, and will be executed again and again in regression testing.</span></li><li><span style="font-size:100%;">Execution might be slow, but it is still faster than manual testing.</span></li><li><span style="font-size:100%;">Tests cannot break for the wrong reason&#8212;When they break we found a bug.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">In the rest of this post I'd like to summarize some experiences I had when I tried to overcome these problems, not by working around them, but by eliminating their causes.</span><br /><br /><span style="font-family: arial;">Most of these problems are rooted in the fact that we are just automating manual tests. By doing so we are not taking into account whether the added computational power, access to different interfaces, and faster execution speed should make us change the way we test systems.</span><br /><br /><span style="font-family: arial;">Considering the fact that a system exposes different interfaces to the environment&#8212;e.g., the user-interface, an interface between front-end and back-end, an interface to a data-store, and interfaces to other systems&#8212;it is obvious that we need to look at each and every interface and test it. More than that we should not only take each interface into account but also avoid testing the functionality in too many different places.</span><br /><br /><span style="font-family: arial;">Let me introduce the example of a store-administration system which allows you to add items to the store, see the current inventory, and remove items. One straightforward manual test case for adding an item would be to go to the 'Add' dialogue, enter a new item with quantity 1, and then go to the 'Display' dialogue to check that it is there. To automate this test case you would instrument exactly all the steps through the user-interface.</span><br /><br /><span style="font-family: arial;">Probably most of the problems I listed above will apply. One way to avoid them in the first place would have been to figure out how this system looks inside.</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">Is there a database? If so, the verification should probably not be performed against the <span class="blsp-spelling-error" id="SPELLING_ERROR_3">UI</span> but against the database.</span></li><li><span style="font-size:100%;">Do we need to interface with a supplier? If so, how should this interaction look?</span></li><li><span style="font-size:100%;">Is the same functionality available via an <span class="blsp-spelling-error" id="SPELLING_ERROR_4">API</span>? If so, it should be tested through the <span class="blsp-spelling-error" id="SPELLING_ERROR_5">API</span>, and the <span class="blsp-spelling-error" id="SPELLING_ERROR_6">UI</span> should just be checked to interact with the <span class="blsp-spelling-error" id="SPELLING_ERROR_7">API</span> correctly.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">This will probably yield a higher number of tests, some of them being much 'smaller' in their resource requirements and executing far faster than the full end-to-end tests. Applying these simple questions will allow us to:</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">write many more tests through the <span class="blsp-spelling-error" id="SPELLING_ERROR_8">API</span>, e.g., to cover many boundary conditions,</span></li><li><span style="font-size:100%;">execute multiple threads of tests on the same machine, giving us a chance to spot race-conditions,</span></li><li><span style="font-size:100%;">start earlier with testing the system, as we can test each interface when it becomes 'quasi-stable',</span></li><li><span style="font-size:100%;">makes maintenance of tests and debugging easier, as the tests break closer to the source of the problem,</span></li><li><span style="font-size:100%;">require fewer machine resources, and still execute in reasonable time.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">I am not advocating the total absence of <span class="blsp-spelling-error" id="SPELLING_ERROR_9">UI</span> tests here. The user interface is just another interface, and so it deserves attention too. However I do think that we are currently focusing most of our testing-efforts on the <span class="blsp-spelling-error" id="SPELLING_ERROR_10">UI</span>. The common attitude, that the <span class="blsp-spelling-error" id="SPELLING_ERROR_11">UI</span> deserves most attention because it is what the user sees, is flawed. Even a perfect <span class="blsp-spelling-error" id="SPELLING_ERROR_12">UI</span> will not satisfy a user if the underlying functionality is corrupt.</span><br /><br /><span style="font-family: arial;">Neither should we abandon our end-to-end tests. They are valuable and no system can be considered tested without them. Again, the question we need to ask ourselves is the ratio between full end-to-end tests and smaller integration tests.</span><br /><br /><span style="font-family: arial;">Unfortunately, there is no free lunch. In order to change the style of test-automation we will also need to change our approach to testing. Successful test-automation needs to:</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">start early in the development cycle,</span></li><li><span style="font-size:100%;">take the internal structure of the system into account,</span></li><li><span style="font-size:100%;">have a feedback loop to developers to influence the system-design.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">Some of these points require quite a change in the way we approach testing. They are only achievable if we work as a single team with our developers. It is crucial that there is an absolute free flow of information between the different roles in this team.</span><br /><br /><span style="font-family: arial;">In previous projects we were able to achieve this by</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">removing any spatial separation between the test engineers and the development engineers. Sitting on the next desk is probably the best way to promote information exchange,</span></li><li><span style="font-size:100%;">using the same tools and methods as the developers,</span></li><li><span style="font-size:100%;">getting involved into daily stand-ups and design-discussions.</span></li></ul><span style="font-size:100%;"><span style="font-family: arial;">This helps not only in getting involved really early (there are projects where test development starts at the same time as development), but it is also a great way to give continuous feedback. Some of the items in the list call for very development-oriented test engineers, as it is easier for them to be recognized as a peer by the development teams.</span><br /><br /><span style="font-family: arial;">To summarize, I figured out that a successful automation project needs:</span><br /></span><ul style="font-family: arial;"><li><span style="font-size:100%;">to take the internal details and exposed interface of the system under test into account,</span></li><li><span style="font-size:100%;">to have many fast tests for each interface (including the <span class="blsp-spelling-error" id="SPELLING_ERROR_13">UI</span>),</span></li><li><span style="font-size:100%;">to verify the functionality at the lowest possible level,<br /></span></li><li><span style="font-size:100%;">to have a set of end-to-end tests,</span></li><li><span style="font-size:100%;">to start at the same time as development,</span></li><li><span style="font-size:100%;">to overcome traditional boundaries between development and testing (spatial, organizational and process boundaries), and<br /></span></li><li><span style="font-size:100%;">to use the same tools as the development team.</span></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:Automating tests vs. test-automation&url=https://testing.googleblog.com/2007/10/automating-tests-vs-test-automation.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/2007/10/automating-tests-vs-test-automation.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/10/automating-tests-vs-test-automation.html#comments' style='font-weight: 500; text-decoration: underline;'>24 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/10/automating-tests-vs-test-automation.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/Markus%20Clermont' rel='tag'> Markus Clermont </a> </span> </div> </div> </div> <div class='post' data-id='5892096707317531881' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/10/overview-of-infrastructure-testing.html' itemprop='url' title='Overview of Infrastructure Testing'> Overview of Infrastructure Testing </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Monday, October 15, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span style="font-size: 100%;"><span style="font-family: arial;">Posted by Marc Kaplan, Test Engineering Lead</span></span><br /><br /><span style="font-family: arial;font-size:100%;" >At Google, we have infrastructure that is shared between many projects. This infrastructure creates a situation where we have a many dependencies in terms of build requirements, but also in terms of test requirements. We've found that we actually need two approaches to deal with these requirements depending on whether we are looking to run larger system tests or smaller unittests, both of which ultimately need to be executed to improve quality.<br /><br />For unittests, we are typically interested in only the module or function that is under test at the time, and we don't care as much about downstream dependencies, except insofar as they relate to the module under test. So we will typically write test mocks to mock out the downstream components that we aren't interested in actually running that simulate their behaviors and failure modes. Of course, this can only be done after understanding how the downstream module works and interfaces with our module.<br /><br />As an example of mocking out a downstream component in <a href="http://labs.google.com/papers/bigtable.html" target="_blank">Bigtable</a>, we want to simulate the failure of <a href="http://labs.google.com/papers/chubby.html" target="_blank">Chubby </a>, our external lockservice, so we we write a Chubby test mock that simulates the various ways that Chubby can interact with Bigtable. We then use this for the Bigtable unittests so that they a) run faster, b) reduce external dependencies and c) enable us to simulate various failure and retry conditions in the Bigtable Chubby related code.<br /><br />There are also cases where we want to simulate components that are actually upstream to the component under test. In these cases we write what is called a test driver. This is very similar to a mock, except that instead of being called by our module (downstream) it calls our module (upstream). For example, if Bigtable component has some <a href="http://labs.google.com/papers/mapreduce.html" target="_blank">Mapreduce</a> specific handling, we might want to write a test driver to simulate these Mapreduce-specific interfaces so we don't have to run the full Mapreduce framework inside our unittest framework. The benefits are all the same as those of using test mocks. In fact, in many cases it may be desirable to use both drivers and mocks, or perhaps multiple of each.<br /><br />In system tests where we're more interested in the true system behaviors and timings, or in other cases where we can't write a driver or mocks we might turn to fault injection. Typically, this involves either completely failing certain components sporadically in system tests, or injecting particular faults via a fault injection layer that we write. Looking back to Bigtable again, since Bigtable uses <a href="http://labs.google.com/papers/gfs.html" target="_blank">GFS</a> when we run system tests, we are running fault injection for GFS by failing actual masters and chunkservers sporadically, and seeing how Bigtable reacts under load to verify that when we deploy new versions of Bigtable that they it will work given the frequent rate of hardware failures. Another approach that we're currently work on is actually simulating the GFS behavior via a fault injection library so we can reduce the need to use private GFS cells which will result in better use of resources.<br /><br />Overall, the use of Test Drivers, Test Mocks, and Fault Injection allows developers and test engineers at Google to test components more accurately, quickly, and above all helps improve quality.</span> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <span style="font-size: 100%;"><span style="font-family: arial;">Posted by Marc Kaplan, Test Engineering Lead</span></span><br /><br /><span style="font-family: arial;font-size:100%;" >At Google, we have infrastructure that is shared between many projects. This infrastructure creates a situation where we have a many dependencies in terms of build requirements, but also in terms of test requirements. We've found that we actually need two approaches to deal with these requirements depending on whether we are looking to run larger system tests or smaller unittests, both of which ultimately need to be executed to improve quality.<br /><br />For unittests, we are typically interested in only the module or function that is under test at the time, and we don't care as much about downstream dependencies, except insofar as they relate to the module under test. So we will typically write test mocks to mock out the downstream components that we aren't interested in actually running that simulate their behaviors and failure modes. Of course, this can only be done after understanding how the downstream module works and interfaces with our module.<br /><br />As an example of mocking out a downstream component in <a href="http://labs.google.com/papers/bigtable.html" target="_blank">Bigtable</a>, we want to simulate the failure of <a href="http://labs.google.com/papers/chubby.html" target="_blank">Chubby </a>, our external lockservice, so we we write a Chubby test mock that simulates the various ways that Chubby can interact with Bigtable. We then use this for the Bigtable unittests so that they a) run faster, b) reduce external dependencies and c) enable us to simulate various failure and retry conditions in the Bigtable Chubby related code.<br /><br />There are also cases where we want to simulate components that are actually upstream to the component under test. In these cases we write what is called a test driver. This is very similar to a mock, except that instead of being called by our module (downstream) it calls our module (upstream). For example, if Bigtable component has some <a href="http://labs.google.com/papers/mapreduce.html" target="_blank">Mapreduce</a> specific handling, we might want to write a test driver to simulate these Mapreduce-specific interfaces so we don't have to run the full Mapreduce framework inside our unittest framework. The benefits are all the same as those of using test mocks. In fact, in many cases it may be desirable to use both drivers and mocks, or perhaps multiple of each.<br /><br />In system tests where we're more interested in the true system behaviors and timings, or in other cases where we can't write a driver or mocks we might turn to fault injection. Typically, this involves either completely failing certain components sporadically in system tests, or injecting particular faults via a fault injection layer that we write. Looking back to Bigtable again, since Bigtable uses <a href="http://labs.google.com/papers/gfs.html" target="_blank">GFS</a> when we run system tests, we are running fault injection for GFS by failing actual masters and chunkservers sporadically, and seeing how Bigtable reacts under load to verify that when we deploy new versions of Bigtable that they it will work given the frequent rate of hardware failures. Another approach that we're currently work on is actually simulating the GFS behavior via a fault injection library so we can reduce the need to use private GFS cells which will result in better use of resources.<br /><br />Overall, the use of Test Drivers, Test Mocks, and Fault Injection allows developers and test engineers at Google to test components more accurately, quickly, and above all helps improve quality.</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:Overview of Infrastructure Testing&url=https://testing.googleblog.com/2007/10/overview-of-infrastructure-testing.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/2007/10/overview-of-infrastructure-testing.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/10/overview-of-infrastructure-testing.html#comments' style='font-weight: 500; text-decoration: underline;'>4 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/10/overview-of-infrastructure-testing.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/Marc%20Kaplan' rel='tag'> Marc Kaplan </a> </span> </div> </div> </div> <div class='post' data-id='5574267107512317494' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/10/testing-google-mashup-editor-class.html' itemprop='url' title='Testing Google Mashup Editor Class'> Testing Google Mashup Editor Class </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Thursday, October 11, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span style="font-size:100%;"><span style="font-family:arial;">Posted by Patrick Copeland, Test Engineering Director<br /><br /></span></span><span style="font-size:100%;"><span style="font-family:arial;">Wanted to let you know about a partnership Google Test Engineering is doing with the University of California, Irvine. We've teamed up with Professor Hadar Ziv to sponsor a course that focuses on preparing students for industry (code.google.com and several other companies are also participating). Naturally, our project focuses on testing. George Pirocanac is heading up this work and recently went down to Irvine to talk about how they will test our mash-up editor. Here's the basic project outline if you are curious.</span><span style="font-weight: bold;font-family:arial;" ><br /><br />Class Project Plan: Testing Google's Mash-up Editor</span><span style="font-weight: bold;font-family:arial;" ><br /><br />Overall Class Goal</span><span style="font-family:arial;">: To understand the basic software functional testing concepts through the experience of a case study of testing the Google Mash-up Editor and to provide meaningful feedback to Google about the effectiveness and usability of the tool.</span><span style="font-weight: bold;font-family:arial;" ><br /><br />Phase I - Gaining Domain expertise and Exploratory Testing</span><span style="font-family:arial;"> (four months)</span><br /><span style="font-family:arial;">Goals: Be able to explain what a mash-up is and why it is becoming important in today's internet. Be able to code a simple mash-up using a javascript api. Be able to code that same mash-up using Google Mash-up Editor tags. Be able to outline the basic features of the Google Mash-up editor. Be able to identify the essential elements of a functional test plan. Create a functional test plan outline for the Google Mash-up editor.</span><span style="font-weight: bold;font-family:arial;" ><br /><br />Phase II - Test Plan Execution over time</span><span style="font-family:arial;"> (Keeping in step with development) (three months)</span><br /><span style="font-family:arial;">Goals: Be able to identify the major challenges in executing a test plan during the life of a software project. Be able to identify testing technologies for dealing with these challenges. Be able to identify the effectiveness of a testing approach. Execute the test plan and provide feedback to Google.</span><span style="font-weight: bold;font-family:arial;" ><br /><br />Phase III - Usability &amp; Competing Technologies Survey</span><span style="font-family:arial;"> (two months)</span><br /><span style="font-family:arial;">Goals: Be able to identify the essential elements of a usability study. Apply the topic of usability to programming. Compare and contrast the GME with three other industry mash-up editors.</span></span><span style=";font-family:arial;font-size:85%;" ><span style="font-size:10;"></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 style="font-size:100%;"><span style="font-family:arial;">Posted by Patrick Copeland, Test Engineering Director<br /><br /></span></span><span style="font-size:100%;"><span style="font-family:arial;">Wanted to let you know about a partnership Google Test Engineering is doing with the University of California, Irvine. We've teamed up with Professor Hadar Ziv to sponsor a course that focuses on preparing students for industry (code.google.com and several other companies are also participating). Naturally, our project focuses on testing. George Pirocanac is heading up this work and recently went down to Irvine to talk about how they will test our mash-up editor. Here's the basic project outline if you are curious.</span><span style="font-weight: bold;font-family:arial;" ><br /><br />Class Project Plan: Testing Google's Mash-up Editor</span><span style="font-weight: bold;font-family:arial;" ><br /><br />Overall Class Goal</span><span style="font-family:arial;">: To understand the basic software functional testing concepts through the experience of a case study of testing the Google Mash-up Editor and to provide meaningful feedback to Google about the effectiveness and usability of the tool.</span><span style="font-weight: bold;font-family:arial;" ><br /><br />Phase I - Gaining Domain expertise and Exploratory Testing</span><span style="font-family:arial;"> (four months)</span><br /><span style="font-family:arial;">Goals: Be able to explain what a mash-up is and why it is becoming important in today's internet. Be able to code a simple mash-up using a javascript api. Be able to code that same mash-up using Google Mash-up Editor tags. Be able to outline the basic features of the Google Mash-up editor. Be able to identify the essential elements of a functional test plan. Create a functional test plan outline for the Google Mash-up editor.</span><span style="font-weight: bold;font-family:arial;" ><br /><br />Phase II - Test Plan Execution over time</span><span style="font-family:arial;"> (Keeping in step with development) (three months)</span><br /><span style="font-family:arial;">Goals: Be able to identify the major challenges in executing a test plan during the life of a software project. Be able to identify testing technologies for dealing with these challenges. Be able to identify the effectiveness of a testing approach. Execute the test plan and provide feedback to Google.</span><span style="font-weight: bold;font-family:arial;" ><br /><br />Phase III - Usability &amp; Competing Technologies Survey</span><span style="font-family:arial;"> (two months)</span><br /><span style="font-family:arial;">Goals: Be able to identify the essential elements of a usability study. Apply the topic of usability to programming. Compare and contrast the GME with three other industry mash-up editors.</span></span><span style=";font-family:arial;font-size:85%;" ><span style="font-size:10;"></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:Testing Google Mashup Editor Class&url=https://testing.googleblog.com/2007/10/testing-google-mashup-editor-class.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/2007/10/testing-google-mashup-editor-class.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/10/testing-google-mashup-editor-class.html#comments' style='font-weight: 500; text-decoration: underline;'>7 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/10/testing-google-mashup-editor-class.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/Patrick%20Copeland' rel='tag'> Patrick Copeland </a> </span> </div> </div> </div> <div class='post' data-id='4301977735229036878' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/10/performance-testing.html' itemprop='url' title='Performance Testing'> Performance Testing </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Monday, October 08, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <p class="MsoPlainText">Posted by <span style=""><span class="blsp-spelling-error" id="SPELLING_ERROR_0">Goranka</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_1">Bjedov</span>, Senior Test Engineer</span><br /><br />This post is my best shot at explaining what I do, why I do it, and why I think it is the right thing to do. Performance testing is a category of testing that seems to evoke strong feelings in people: feelings of fear (Oh, my God, I have no idea what to do because performance testing is so hard!), feelings of inadequacy (We bought this tool that does every aspect of performance testing, we paid so much for it, and we are not getting anything done!), feelings of confusion (So, what the heck am I supposed to be doing again?), and I don't think this is necessary.<br /><br />Think of performance testing as another tool in your testing arsenal - something you will do when you need to. It explores several system qualities, that can be simplified to:<br /></p><ul><li> Speed - does the system respond quickly enough</li><li> Capacity - is the infrastructure sized adequately</li><li> Scalability - can the system grow to handle future volumes</li><li> Stability - does the system behave correctly under load</li></ul><p class="MsoPlainText"> So, I do performance testing of a service when risk analysis indicates that failing in any of the above categories would be more costly to the company than performing the tests. (Which, if your name is Google and you care about your brand, happens with any service you launch.) Note that I am talking about services - I work almost exclusively with servers and spend no time worrying about client-side rendering/processing issues. While those are becoming increasingly more important, and have always been more complex than my work, I consider those to be a part of functionality tests, and they are designed, created and executed by functional testing teams.<br /><br />Another interesting thing about performance testing is that you will never be able to be 100% "right" or 100% "done. Accept it, deal with it, and move on. Any system in existence today will depend on thousands of different parameters, and if I spent the time analyzing each one of them, understanding the relationships between each two or each three, graphing their impact curves, trying to non-<span class="blsp-spelling-error" id="SPELLING_ERROR_2">dimensionalize</span> them, I would still be testing my first service two years later. The thought of doing anything less filled me with horror (They cannot seriously expect me to provide meaningful performance results in less than a year, can they?) but I have since learned that I can provide at least 90% of meaningful information to my customers by applying only 10% of my total effort and time. And, 90% is more than enough for vast majority of problems.<br /><br />So, here is what I really do - I create benchmarks. If I am lucky and have fantastic information about current usage patterns of a particular product (which I usually do), I will make sure this benchmark covers most operations that are top resource hogs (either per single use or cumulative). I'll run this benchmark with different loads (number of virtual users) against a loosely controlled system (it would be nice to have 100 machines all to myself for every service we have, which I can use once a day or once a week, but that would be expensive and unrealistic) and investigate its behavior. Which transactions are taking the most time? Which transactions seem to get progressively worse with increasing load? Which transactions seem unstable (I cannot explain their behavior)? I call this exploratory performance testing, and I'll repeat my tests until I am convinced I am observing real system behavior. While I am doing this, I make sure I am not getting biased by investigating the code. If I have questions, I ask programmers, but I know they are biased, and I will avoid getting biased myself!<br /><br />Once I have my graphs (think, interesting transaction latencies and throughput vs. load here) I meet with the development team and discuss the findings. Usually, there is one or two things they know and have been working on, and a few more they were unaware of. Sometimes, they look over my benchmark and suggest changes (could you make the ratio 80:20, and not 50:50?) After this meeting, we create our final benchmark, I modify the performance testing scripts, and now this benchmark will run as often as possible, but hopefully at least once a night. And, here is the biggest value of this effort: if there is a code change that has impacted performance in an unacceptable way, you will find out about it the next day. Not a week or a month later (How many of us remember what we did in the last month? So, why expect our developers to do so?)<br /><br />Here is why I think this is the right thing to do: I have seen more bad code developed as a result of premature performance optimizations - before the team even thought they had a problem! Please don't do that. Develop your service in a clean, maintainable and extensible manner. Let me test it, and keep regression testing it. If we find we have a problem in a particular area, we can then address that problem easily - because our code is not obfuscated with performance optimization that have improved code paths that execute once a month by 5%.<br /><br />I can usually do this in two - four weeks depending on the complexity of the project. Occasionally, we will find an issue that cannot be explained or understood with performance tests. At that point in time, we look under the hood. This is where performance profiling and performance modeling come in. And, both of those are considerably more complex than performance testing. Both great tools, but should be used only when the easy tool fails.<br /><br />Tools, tools, tools... So, what do we use? I gave a presentation at <a href="http://video.google.com/videoplay?docid=-6891978643577501895">Google Test Automation Conference in <st1:city st="on"><st1:place st="on">London</st1:place></st1:city></a> on exactly this topic. I use open source tools. I discuss the reasons why in the presentation. In general, even if you have decided to go one of the other two routes (vendor tools or develop your own) check out what is available. You may find out that you will get a lot of information about your service using <span class="blsp-spelling-error" id="SPELLING_ERROR_3">JMeter</span> and spending some time playing around with it. Sure, you can also spend $500K and get similar information or you can spend two years developing "the next best performance testing tool ever," but before you are certain free is not good enough, why would you want to?<br /><br />Final word: monitor your services during performance tests. If you do not have service related monitoring developed and set up to be used during live operations, you do not need performance testing. If the risks of your service failing are not important enough that you would want to know about it *before* it happens, then you should not be wasting time or money on performance testing. I am incredibly lucky in this area - Google infrastructure is developed by a bunch of people who, if they had a meeting where the topic would be "How to make <span class="blsp-spelling-error" id="SPELLING_ERROR_4">Goranka's</span> life easy?", could not have done better. I love them - they make my job trivial. At a minimum, I monitor CPU, memory and I/O usage. I cannot see a case when you would want to do less, but you may want to do a lot more on occasion.<br /></p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <p class="MsoPlainText">Posted by <span style=""><span class="blsp-spelling-error" id="SPELLING_ERROR_0">Goranka</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_1">Bjedov</span>, Senior Test Engineer</span><br /><br />This post is my best shot at explaining what I do, why I do it, and why I think it is the right thing to do. Performance testing is a category of testing that seems to evoke strong feelings in people: feelings of fear (Oh, my God, I have no idea what to do because performance testing is so hard!), feelings of inadequacy (We bought this tool that does every aspect of performance testing, we paid so much for it, and we are not getting anything done!), feelings of confusion (So, what the heck am I supposed to be doing again?), and I don't think this is necessary.<br /><br />Think of performance testing as another tool in your testing arsenal - something you will do when you need to. It explores several system qualities, that can be simplified to:<br /></p><ul><li> Speed - does the system respond quickly enough</li><li> Capacity - is the infrastructure sized adequately</li><li> Scalability - can the system grow to handle future volumes</li><li> Stability - does the system behave correctly under load</li></ul><p class="MsoPlainText"> So, I do performance testing of a service when risk analysis indicates that failing in any of the above categories would be more costly to the company than performing the tests. (Which, if your name is Google and you care about your brand, happens with any service you launch.) Note that I am talking about services - I work almost exclusively with servers and spend no time worrying about client-side rendering/processing issues. While those are becoming increasingly more important, and have always been more complex than my work, I consider those to be a part of functionality tests, and they are designed, created and executed by functional testing teams.<br /><br />Another interesting thing about performance testing is that you will never be able to be 100% "right" or 100% "done. Accept it, deal with it, and move on. Any system in existence today will depend on thousands of different parameters, and if I spent the time analyzing each one of them, understanding the relationships between each two or each three, graphing their impact curves, trying to non-<span class="blsp-spelling-error" id="SPELLING_ERROR_2">dimensionalize</span> them, I would still be testing my first service two years later. The thought of doing anything less filled me with horror (They cannot seriously expect me to provide meaningful performance results in less than a year, can they?) but I have since learned that I can provide at least 90% of meaningful information to my customers by applying only 10% of my total effort and time. And, 90% is more than enough for vast majority of problems.<br /><br />So, here is what I really do - I create benchmarks. If I am lucky and have fantastic information about current usage patterns of a particular product (which I usually do), I will make sure this benchmark covers most operations that are top resource hogs (either per single use or cumulative). I'll run this benchmark with different loads (number of virtual users) against a loosely controlled system (it would be nice to have 100 machines all to myself for every service we have, which I can use once a day or once a week, but that would be expensive and unrealistic) and investigate its behavior. Which transactions are taking the most time? Which transactions seem to get progressively worse with increasing load? Which transactions seem unstable (I cannot explain their behavior)? I call this exploratory performance testing, and I'll repeat my tests until I am convinced I am observing real system behavior. While I am doing this, I make sure I am not getting biased by investigating the code. If I have questions, I ask programmers, but I know they are biased, and I will avoid getting biased myself!<br /><br />Once I have my graphs (think, interesting transaction latencies and throughput vs. load here) I meet with the development team and discuss the findings. Usually, there is one or two things they know and have been working on, and a few more they were unaware of. Sometimes, they look over my benchmark and suggest changes (could you make the ratio 80:20, and not 50:50?) After this meeting, we create our final benchmark, I modify the performance testing scripts, and now this benchmark will run as often as possible, but hopefully at least once a night. And, here is the biggest value of this effort: if there is a code change that has impacted performance in an unacceptable way, you will find out about it the next day. Not a week or a month later (How many of us remember what we did in the last month? So, why expect our developers to do so?)<br /><br />Here is why I think this is the right thing to do: I have seen more bad code developed as a result of premature performance optimizations - before the team even thought they had a problem! Please don't do that. Develop your service in a clean, maintainable and extensible manner. Let me test it, and keep regression testing it. If we find we have a problem in a particular area, we can then address that problem easily - because our code is not obfuscated with performance optimization that have improved code paths that execute once a month by 5%.<br /><br />I can usually do this in two - four weeks depending on the complexity of the project. Occasionally, we will find an issue that cannot be explained or understood with performance tests. At that point in time, we look under the hood. This is where performance profiling and performance modeling come in. And, both of those are considerably more complex than performance testing. Both great tools, but should be used only when the easy tool fails.<br /><br />Tools, tools, tools... So, what do we use? I gave a presentation at <a href="http://video.google.com/videoplay?docid=-6891978643577501895">Google Test Automation Conference in <st1:city st="on"><st1:place st="on">London</st1:place></st1:city></a> on exactly this topic. I use open source tools. I discuss the reasons why in the presentation. In general, even if you have decided to go one of the other two routes (vendor tools or develop your own) check out what is available. You may find out that you will get a lot of information about your service using <span class="blsp-spelling-error" id="SPELLING_ERROR_3">JMeter</span> and spending some time playing around with it. Sure, you can also spend $500K and get similar information or you can spend two years developing "the next best performance testing tool ever," but before you are certain free is not good enough, why would you want to?<br /><br />Final word: monitor your services during performance tests. If you do not have service related monitoring developed and set up to be used during live operations, you do not need performance testing. If the risks of your service failing are not important enough that you would want to know about it *before* it happens, then you should not be wasting time or money on performance testing. I am incredibly lucky in this area - Google infrastructure is developed by a bunch of people who, if they had a meeting where the topic would be "How to make <span class="blsp-spelling-error" id="SPELLING_ERROR_4">Goranka's</span> life easy?", could not have done better. I love them - they make my job trivial. At a minimum, I monitor CPU, memory and I/O usage. I cannot see a case when you would want to do less, but you may want to do a lot more on occasion.<br /></p> <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:Performance Testing&url=https://testing.googleblog.com/2007/10/performance-testing.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/2007/10/performance-testing.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/10/performance-testing.html#comments' style='font-weight: 500; text-decoration: underline;'>23 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/10/performance-testing.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/Goranka%20Bjedov' rel='tag'> Goranka Bjedov </a> </span> </div> </div> </div> <div class='post' data-id='8426718412343348033' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/10/post-release-closing-loop_02.html' itemprop='url' title='Post Release: Closing the loop'> Post Release: Closing the loop </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Tuesday, October 02, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span style="font-size:100%;">Posted by Michael Bachman<span class="HcCDpe"><span class="blsp-spelling-error" id="SPELLING_ERROR_0"></span></span>, Test Engineering Manager</span><br /><br />A testing organization's job is not done with the release of a product. As the software development cycle does not end with the release of the product but has an extension into the post-release diagnostics and evaluation. Learning from post-release metrics like product performance, defects, and behavior after it is in production (or in the field) provides valuable input into how to adjust future testing and development techniques. Measuring product defect trends and performance, and analyzing those results, can identify holes in test coverage, prevent bugs, plug gaps in the release cycle or product life cycle, and determine if the pre-release test environment was adequately representative of key customer scenarios.<br /><br />Here are a few metrics that can help jump-start this effort<br /><br />Pre- versus post-production defect ratio: This metric measures the ratio of total number of defects found before production divided by the overall number of defects in the product (including the post-release issues). This lets a team measure how many defects are being caught before release. This effort supplements the age old valuable practice of partnering with Product Support to measure incidents/defect rate. The goal is not and should not be to indulge in the blame game of "A defect found after release is test's "fault," " but as a means to find ways to make the product release cycle better. The thing to focus on is to identify what were the causes for the issue - gaps in the release cycle, communication mishaps between product, development, and testing, inadequate test environments, or the overall testability of a product. There may not be a perfect metric, but obvious ones might be: time to resolutions (how long it takes to react to a broken issue), cost to the customer, or cost to customer support. The main point is to agree on a cross-organizational metric, track it, do the root cause analysis, and make the time to change.<br /><br />Breakdown of defects by component or functional area: In conjunction with monitoring which defects are found in production, categorizing them by functional area and component provides the necessary information to highlight trends and, more specifically, problematic areas. When a problematic component is identified, the test team can fill holes in test coverage, unit test coverage, product usability issues or the life cycle managing that functional area. Also, trending defects by component over time has additional advantages like - this data provides a better sense of the quality of particular components as they age, also provides the information of how effective the changes(if any) that were introduced in the engineering practices resulting in better quality and finally measure of introduction of new functionality caused any de-stabilizing effects to the system. This metric will allow product teams in making informed decisions regarding the product. Potential outcomes are resources allocation changes, feature deprecation or redesign of the features.<br /><br />Performance measurements (CPU usage, memory consumption, disk load, database load, latency, etc.): Without going into the various load and performance (L&amp;P) measurements one can monitor within a product (since that can be a whole separate article in itself :) ) the product teams should ensure they have mechanisms to measure key and product relevant metrics can be collected. In order to gauge the effectiveness of the test environments these measurements need to obtained both in the test labs and production environments. Identifying these mismatches allows test organizations to correct any topology issues early and before any subsequent releases (or similar releases).<br /><br />Furthermore analysis of these could expose multiple causes of why the product behavior was different in production than in test labs. Some examples (like we have found at Google) of these issues are : different machine hardware, load mismatch on the system, localized tests not measuring round-trip latency, the number of concurrent users hitting the product simultaneously (your testing team compared to the potential millions of users in production). It is important to remember that, the most important point here to measure and monitor the performance of the product as well as determine the adequacy of the test environment. When a performance issue is found in production, ask yourself "could we have caught that in the test environment?"<br /><br />Are users or your monitoring systems finding the defects? Having reliable monitoring and debugging systems, logs, and notifications are key in reacting immediately to large defects in production, as well as potentially finding the defect before your users do. Some of the best practices of engineering teams (and those followed at Google) are real-time notifications of exceptions, load, and performance, pager alerts when systems are unavailable, as well as robust logs to help developers and testing debug the system state before and after a crash. There are many open source and commercial solutions to these pieces rather than building in-house solutions. The bulk of the effort in setting up reliable monitoring typically lies in development, but it is key for test teams to assist in identifying the need and also ensure they are utilized in their test environments. This not only allows the testing organization to test the functionality of the monitoring tools, but also alerts testing of defects that might have slipped through and are not directly visible on a front-end.<br /><br />So, what does this get you? A solid picture of the product's quality and performance trend over time. Measuring lets testing tweak their coverage and environments, as well as analyze how the team works together. Reacting to the findings helps open communication channels between development, production, and testing, and lets them join together to debug and reproduce defects and eventually reduce defects. Every part of the larger team can watch defect trends; help prioritize resources and features, and better increase unit test, system test, and performance test coverage. Getting to a robust, real-time defect, performance, monitoring framework takes effort from all teams, but, in the end, everyone can reap the benefit, especially, and most important, your users. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <span style="font-size:100%;">Posted by Michael Bachman<span class="HcCDpe"><span class="blsp-spelling-error" id="SPELLING_ERROR_0"></span></span>, Test Engineering Manager</span><br /><br />A testing organization's job is not done with the release of a product. As the software development cycle does not end with the release of the product but has an extension into the post-release diagnostics and evaluation. Learning from post-release metrics like product performance, defects, and behavior after it is in production (or in the field) provides valuable input into how to adjust future testing and development techniques. Measuring product defect trends and performance, and analyzing those results, can identify holes in test coverage, prevent bugs, plug gaps in the release cycle or product life cycle, and determine if the pre-release test environment was adequately representative of key customer scenarios.<br /><br />Here are a few metrics that can help jump-start this effort<br /><br />Pre- versus post-production defect ratio: This metric measures the ratio of total number of defects found before production divided by the overall number of defects in the product (including the post-release issues). This lets a team measure how many defects are being caught before release. This effort supplements the age old valuable practice of partnering with Product Support to measure incidents/defect rate. The goal is not and should not be to indulge in the blame game of "A defect found after release is test's "fault," " but as a means to find ways to make the product release cycle better. The thing to focus on is to identify what were the causes for the issue - gaps in the release cycle, communication mishaps between product, development, and testing, inadequate test environments, or the overall testability of a product. There may not be a perfect metric, but obvious ones might be: time to resolutions (how long it takes to react to a broken issue), cost to the customer, or cost to customer support. The main point is to agree on a cross-organizational metric, track it, do the root cause analysis, and make the time to change.<br /><br />Breakdown of defects by component or functional area: In conjunction with monitoring which defects are found in production, categorizing them by functional area and component provides the necessary information to highlight trends and, more specifically, problematic areas. When a problematic component is identified, the test team can fill holes in test coverage, unit test coverage, product usability issues or the life cycle managing that functional area. Also, trending defects by component over time has additional advantages like - this data provides a better sense of the quality of particular components as they age, also provides the information of how effective the changes(if any) that were introduced in the engineering practices resulting in better quality and finally measure of introduction of new functionality caused any de-stabilizing effects to the system. This metric will allow product teams in making informed decisions regarding the product. Potential outcomes are resources allocation changes, feature deprecation or redesign of the features.<br /><br />Performance measurements (CPU usage, memory consumption, disk load, database load, latency, etc.): Without going into the various load and performance (L&amp;P) measurements one can monitor within a product (since that can be a whole separate article in itself :) ) the product teams should ensure they have mechanisms to measure key and product relevant metrics can be collected. In order to gauge the effectiveness of the test environments these measurements need to obtained both in the test labs and production environments. Identifying these mismatches allows test organizations to correct any topology issues early and before any subsequent releases (or similar releases).<br /><br />Furthermore analysis of these could expose multiple causes of why the product behavior was different in production than in test labs. Some examples (like we have found at Google) of these issues are : different machine hardware, load mismatch on the system, localized tests not measuring round-trip latency, the number of concurrent users hitting the product simultaneously (your testing team compared to the potential millions of users in production). It is important to remember that, the most important point here to measure and monitor the performance of the product as well as determine the adequacy of the test environment. When a performance issue is found in production, ask yourself "could we have caught that in the test environment?"<br /><br />Are users or your monitoring systems finding the defects? Having reliable monitoring and debugging systems, logs, and notifications are key in reacting immediately to large defects in production, as well as potentially finding the defect before your users do. Some of the best practices of engineering teams (and those followed at Google) are real-time notifications of exceptions, load, and performance, pager alerts when systems are unavailable, as well as robust logs to help developers and testing debug the system state before and after a crash. There are many open source and commercial solutions to these pieces rather than building in-house solutions. The bulk of the effort in setting up reliable monitoring typically lies in development, but it is key for test teams to assist in identifying the need and also ensure they are utilized in their test environments. This not only allows the testing organization to test the functionality of the monitoring tools, but also alerts testing of defects that might have slipped through and are not directly visible on a front-end.<br /><br />So, what does this get you? A solid picture of the product's quality and performance trend over time. Measuring lets testing tweak their coverage and environments, as well as analyze how the team works together. Reacting to the findings helps open communication channels between development, production, and testing, and lets them join together to debug and reproduce defects and eventually reduce defects. Every part of the larger team can watch defect trends; help prioritize resources and features, and better increase unit test, system test, and performance test coverage. Getting to a robust, real-time defect, performance, monitoring framework takes effort from all teams, but, in the end, everyone can reap the benefit, especially, and most important, your users. <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:Post Release: Closing the loop&url=https://testing.googleblog.com/2007/10/post-release-closing-loop_02.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/2007/10/post-release-closing-loop_02.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/10/post-release-closing-loop_02.html#comments' style='font-weight: 500; text-decoration: underline;'>9 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/10/post-release-closing-loop_02.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/Michael%20Bachman' rel='tag'> Michael Bachman </a> </span> </div> </div> </div> <div class='post' data-id='1496456913082308222' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/09/but-it-works-on-my-machine.html' itemprop='url' title='But it works on my machine!'> But it works on my machine! </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Tuesday, September 25, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <div style="text-align: center; font-size: 10pt; font-family: Verdana; margin-top: 0pt; margin-bottom: 0pt;"><div style="text-align: left;"><span style="font-size: 100%;"><span style="font-family: arial;">Posted by John Thomas, Software Engineer<br /></span></span></div> <div style="text-align: left; font-size: 10pt; font-family: Verdana; margin-top: 0pt; margin-bottom: 0pt;"> <p style="text-align: justify;"><span style="font-family: Arial; font-size: 100%; color: green;">We thought you might be interested in another article from our internal monthly testing newsletter called CODE GREEN... Originally titled: "Opinion: But it works on my machine!"<br /></span></p><p style="text-align: justify;"><span style="font-family:Arial;">We spent so much time hearing about "make your tests small and run fast." While this is important for quick CL verification, system level testing is important, too, and doesn't get enough air time. </span> </p> <p style="text-align: justify;"><span style="font-family:Arial;">You write cool features. You write lots and lots of unit tests to make sure your features work. You make sure the unit tests run as part of your project's continuous build. Yet when the QA engineer tries out a few user scenarios, she finds many defects. She logs them as bugs. You try to reproduce them, but ... you can't!<br /> <br /> Sound familiar? It might to a lot of you who deal with complex systems that touch many other dependent systems. Want to test a simple service that just talks to a database? Simple, write a few unit tests with a mocked-out database. Want to test a service that connects to authentication to manage user accounts, talks to a risk engine, a biller, <i>and</i> a database? Now that's a different story!</span></p> <span style="font-family:Arial;"> </span><p style="text-align: justify;"> <span style="font-family:Arial;"> <span style="font-weight: bold;">So what are system level tests again?</span><br /> System level tests to the rescue. They're also referred to as integration tests, scenario tests, and end-end tests. No matter what they're called, these tests are a vital part of any test strategy. They wait for screen responses, they punch in HTML form fields, they click on buttons and links, they verify text on the UI (sometimes in different languages and locales). Heck, sometimes they even poke open inboxes and verify email content!<br /> <br /> <span style="font-weight: bold;">But I have a gazillion unit tests and I don't need system level tests!</span><br /> Sure you do. Unit tests are useful in helping you quickly decide whether your latest code changes haven't caused your existing code to regress. They are an invaluable part of the agile developers' tool kit. But when code is finally packaged and deployed, it could look and behave very differently. And no amount of unit tests can help you decide whether that awesome UI feature you designed works the way it was intended, or that one of the services your feature depended on is broken or not behaving as expected. If you think of a "testing diet," system level tests are like carbohydrates -- they are a crucial part of your diet, but only in the right amount!<br /> <br /> System level tests provide that sense of comfort that everything works the way it should, when it lands in the customer's hands. In short, they're the closest thing to simulating your customers. And that makes them pretty darn valuable.<br /> <br /> <span style="font-weight: bold;">Wait a minute -- how stable are these tests?</span><br /> Very good question. It should be pretty obvious that if you test a full blown deployment of any large, complex system you're going to run into some stability issues. Especially since large, complex systems consist of components that talk to many other components, sometimes asynchronously. And real world systems aren't perfect. Sometimes the database doesn't respond at all, sometimes the web server responds a few seconds later, and sometimes a simple confirmation message takes forever to reach an email inbox!<br /> <br /> Automated system level tests are sensitive to such issues, and sometimes report false failures. The key is utilizing them effectively, quickly identifying and fixing false failures, and pairing them up with the right set of small, fast tests.<br /> <br /></span></p></div> </div> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <div style="text-align: center; font-size: 10pt; font-family: Verdana; margin-top: 0pt; margin-bottom: 0pt;"><div style="text-align: left;"><span style="font-size: 100%;"><span style="font-family: arial;">Posted by John Thomas, Software Engineer<br /></span></span></div> <div style="text-align: left; font-size: 10pt; font-family: Verdana; margin-top: 0pt; margin-bottom: 0pt;"> <p style="text-align: justify;"><span style="font-family: Arial; font-size: 100%; color: green;">We thought you might be interested in another article from our internal monthly testing newsletter called CODE GREEN... Originally titled: "Opinion: But it works on my machine!"<br /></span></p><p style="text-align: justify;"><span style="font-family:Arial;">We spent so much time hearing about "make your tests small and run fast." While this is important for quick CL verification, system level testing is important, too, and doesn't get enough air time. </span> </p> <p style="text-align: justify;"><span style="font-family:Arial;">You write cool features. You write lots and lots of unit tests to make sure your features work. You make sure the unit tests run as part of your project's continuous build. Yet when the QA engineer tries out a few user scenarios, she finds many defects. She logs them as bugs. You try to reproduce them, but ... you can't!<br /> <br /> Sound familiar? It might to a lot of you who deal with complex systems that touch many other dependent systems. Want to test a simple service that just talks to a database? Simple, write a few unit tests with a mocked-out database. Want to test a service that connects to authentication to manage user accounts, talks to a risk engine, a biller, <i>and</i> a database? Now that's a different story!</span></p> <span style="font-family:Arial;"> </span><p style="text-align: justify;"> <span style="font-family:Arial;"> <span style="font-weight: bold;">So what are system level tests again?</span><br /> System level tests to the rescue. They're also referred to as integration tests, scenario tests, and end-end tests. No matter what they're called, these tests are a vital part of any test strategy. They wait for screen responses, they punch in HTML form fields, they click on buttons and links, they verify text on the UI (sometimes in different languages and locales). Heck, sometimes they even poke open inboxes and verify email content!<br /> <br /> <span style="font-weight: bold;">But I have a gazillion unit tests and I don't need system level tests!</span><br /> Sure you do. Unit tests are useful in helping you quickly decide whether your latest code changes haven't caused your existing code to regress. They are an invaluable part of the agile developers' tool kit. But when code is finally packaged and deployed, it could look and behave very differently. And no amount of unit tests can help you decide whether that awesome UI feature you designed works the way it was intended, or that one of the services your feature depended on is broken or not behaving as expected. If you think of a "testing diet," system level tests are like carbohydrates -- they are a crucial part of your diet, but only in the right amount!<br /> <br /> System level tests provide that sense of comfort that everything works the way it should, when it lands in the customer's hands. In short, they're the closest thing to simulating your customers. And that makes them pretty darn valuable.<br /> <br /> <span style="font-weight: bold;">Wait a minute -- how stable are these tests?</span><br /> Very good question. It should be pretty obvious that if you test a full blown deployment of any large, complex system you're going to run into some stability issues. Especially since large, complex systems consist of components that talk to many other components, sometimes asynchronously. And real world systems aren't perfect. Sometimes the database doesn't respond at all, sometimes the web server responds a few seconds later, and sometimes a simple confirmation message takes forever to reach an email inbox!<br /> <br /> Automated system level tests are sensitive to such issues, and sometimes report false failures. The key is utilizing them effectively, quickly identifying and fixing false failures, and pairing them up with the right set of small, fast tests.<br /> <br /></span></p></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:But it works on my machine!&url=https://testing.googleblog.com/2007/09/but-it-works-on-my-machine.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/2007/09/but-it-works-on-my-machine.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/09/but-it-works-on-my-machine.html#comments' style='font-weight: 500; text-decoration: underline;'>4 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/09/but-it-works-on-my-machine.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/John%20Thomas' rel='tag'> John Thomas </a> </span> </div> </div> </div> <div class='post' data-id='2053067868156320857' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/09/seleniums-inventor.html' itemprop='url' title='Selenium&#39;s Inventor'> Selenium's Inventor </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Wednesday, September 19, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span style="font-size:100%;"><span style="font-family:arial;">Posted by Patrick Copeland, Test Engineering Director<br /></span><br /><a href="//picasaweb.google.com/TestEngTeam/CodeGreen/photo?authkey=IA66TjDvtik#5112064269199230642"><img src="//lh6.google.com/TestEngTeam/RvGzXjKWRrI/AAAAAAAAADg/6n6WPe50yJQ/s400/big_logo.jpg"></a><br /></span><span style=";font-family:Arial;font-size:100%;color:green;" >We thought you might be interested in some articles from our internal monthly testing newsletter called CODE GREEN...<br /><br />Many projects at Google have started using or are considering using Selenium. We recently interviewed Noogler (new people to Google) Jason Huggins, who is the creator and developer of <a href="http://www.openqa.org/selenium/" target="_blank"><span style="color:green;">Selenium</span></a>, to learn about how it all started and where it's going. <o:p></o:p></span> <p><span style=";font-family:Arial;font-size:100%;color:green;" >[Side note: Even before his first day at the Googleplex, Jason showed an amazing dedication to Google. After leaving <st1:city st="on"><st1:place st="on">Chicago</st1:place></st1:city> with the big moving truck, he and his family had to stop after just a few hours because of an ice storm. Cars sliding off the road left and right. Further along, in <st1:state st="on"><st1:place st="on">Kansas</st1:place></st1:state>, one of his kids caught pneumonia. His family stayed in the local hospital while Jason drove on. Heading west, there was a big snow storm in <st1:state st="on"><st1:place st="on">Colorado</st1:place></st1:state>, which he wanted to avoid. He drove further south and ended up in a rare (but really real) <a href="http://earthobservatory.nasa.gov/NaturalHazards/natural_hazards_v2.php3?img_id=14141" target="_blank"><span style="text-decoration: none;color:green;" >dust storm over the Border States</span></a>. He promised us some great video footage of his drive through tumbleweeds. He finally arrived and has settled in and is looking forward to calmer times in the Bay Area. After that trip, he isn't even worried about earthquakes, fires, mud slides, or traffic on the 101.]</span></p><p><span style="font-family: arial;font-size:100%;" >Couple of GTAC Videos with Jason: <a href="//youtube.com/watch?v=qxBatJ1N_Og">SeleniumRC</a></span><span style="font-size:100%;"><span style="font-family: arial;">, </span><a style="font-family: arial;" href="//youtube.com/watch?v=Vlz-WmcrBL8">Selenium vs WebDriver</a></span><br /><span style=";font-family:Arial;font-size:100%;color:green;" ><o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: Why did you invent Selenium? What was the motivation? </span></b></span><span style=";font-family:Arial;font-size:100%;" ><br /><b>Huggins:</b> Selenium was extracted from a web-based (Python + Plone!) time-and-expense (T&amp;E) application my team and I were building for my previous employer. One of the mandates for the new T&amp;E app was that it needed to be "fast, fast, fast." The legacy application was a client-server Lotus Notes application and wasn't scalable to the current number of offices and employees at the time. To live up to the "fast, fast, fast" design goal, we tried to improve and speed up the user experience as much as possible. For example, expense reports can get pretty long for people who travel a lot. No matter how many default rows we put in a blank expense form, people often needed to add more rows of expense items to their reports. So we added an "Add row" button to the expense report form. To make this "fast, fast, fast," I decided to use a button that triggered JavaScript to dynamically add one blank row to the form. At the time (Spring 2004), however, JavaScript was considered buggy and evil by most web developers, so I caught a lot of flak for not going with the classic approach of POSTing the form and triggering a complete page refresh with the current form data, plus one blank row.<o:p></o:p></span></p> <p><span style=";font-family:Arial;font-size:100%;" >Going down the road of using JavaScript had consequences. For one, we had a really, really difficult time testing that little "Add row" button. And sadly, it broke often. One week "Add row" would be working in Mozilla (Firefox was pre-1.0), but broken in Internet Explorer. And of course, nothing was working in Safari since few developers were allowed to have Macs. ;-) The following week, we'd open a bug saying "'Add row' is broken in IE!!" The developer assigned to the issue would fix and test it in IE, but not test for regressions in Mozilla. So, "Add row" would now be broken in Mozilla, and I'd have to open a ticket saying "'Add row' is now broken in Mozilla!!!". Unlike most other corporate IT shops, we didn't have the luxury of telling all employees to use a single browser, and developers didn't want to manually test every feature in all supported browsers every time. Also, we had a very tiny budget and commercial testing tools were -- and still are -- ridiculously over-priced on a per-seat basis. The T&amp;E project was done the "<st1:street st="on"><st1:address st="on">Agile Way</st1:address></st1:street>" -- every developer does testing -- so shelling out thousands of dollars per developer for a testing tool wasn't going to happen. Never mind the fact that there were no commercial tools that did what we needed anyway!<o:p></o:p></span></p> <p><span style=";font-family:Arial;font-size:100%;" >After many months of trial and error and various code workarounds, I came to the conclusion I needed a testing tool that would let me functional-test JavaScript-enhanced web user interfaces (aka "DHTML" or now "<st1:city st="on"><st1:place st="on">Ajax</st1:place></st1:city>"). More specifically, I needed to test the browser UIs: Internet Explorer, Mozilla Firefox, and Safari. There were no commercial apps at the time that could do this, and the only open source option was JsUnit, which was more focused on unit testing pure JavaScript functions, rather than being a higher-level black-box/smoke-test walk through a web app. So we needed to write our own tool. Our first attempt was a Mozilla extension called "driftwood" (never <span style="font-size:100%;">released), coded by Andrew McCormick, another co-worker of mine at the time. It did make testing the "Add row" button possible, but since it was Mozilla-only, it wasn't what we needed for testing in all browsers. Paul Gross and I started over, and I started to educate myself on functional testing tools and techniques and stumbled upon Ward Cunningham's Framework for Integrated Testing (FIT). I originally set out to implement "FIT for JavaScript," but quickly realized we were drifting away from the FIT API, so Selenium became its own thing.</span></span><span style=";font-family:Arial;font-size:100%;" ><o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: Why does the world need another test tool?</span></b><b><span style="font-family:Arial;"><br />Huggins: </span></b></span><span style=";font-family:Arial;font-size:100%;" >At the time I created Selenium, had there been another testing tool that could test JavaScript UI features in all browsers on all platforms, believe me, I would have saved lots of time *not* writing my own tool.<o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: What's special about it?</span></b></span><span style=";font-family:Arial;font-size:100%;" ><br /><b>Huggins:</b> Well, maybe the right question is "What's &#8220;lucky&#8221; about it? Selenium was created in a time when JavaScript was considered "bad" and generally avoided by most professional web developers. Then Google Maps hit the scene a year later, the term "<st1:city st="on"><st1:place st="on">Ajax</st1:place></st1:city>" was coined, and BOOM! Overnight, JavaScript became "good." Also, Firefox started stealing market share from IE. The combination of needing to test 1) JavaScript features 2) in several browsers (not just IE) was a "right place, right time" moment for Selenium.<o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: When did you realize that Selenium was a big deal? What was the tipping point? </span></b></span><span style=";font-family:Arial;font-size:100%;" ><br /><b>Huggins: </b>When I started being asked to give presentations or write about Selenium by people I didn't know. The tipping point for Selenium technically relied on two things: 1) the Selenium IDE for Firefox, written by Shinya Kasatani, which made installation and the first-hour experience tons better for new users. And 2), Selenium Remote Control (RC) created by Paul Hammant, and extended by Dan Fabulich, Nelson Sproul, and Patrick Lightbody, which let developers write their tests in Java, C#, Perl, Python, or Ruby, and not have to write all their tests in the original FIT-like HTML tables. Socially, if Google Maps or Gmail never existed and thus the whole Ajax gold rush, I wonder if JavaScript would still be considered "bad," with a similar "why bother?" attitude to testing it. <o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: Have you discovered any interesting teams using Selenium in ways you'd never intended? </span></b></span><span style=";font-family:Arial;font-size:100%;" ><br /><b>Huggins:</b> At my previous company, I did see some developers write Selenium scripts to create their time and expense reports for them from YAML or XLS files. Since we hadn't exposed a back-end API, automating the browser for data entry was the next best thing. It was never designed for this purpose, but I started (ab)using it as coded bug reports. Asking users for steps on how to reproduce a bug naturally lends itself to looking like a Selenium test for that bug. Also, I've used the Selenium IDE Firefox plug-in to enter NBC's "Deal or No Deal" contest on their website from home, but I stopped doing that when I read in the fine print that the use of automation tools to enter their contest was grounds for disqualification. <o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: What advice do you have to offer Google groups interested in Selenium?<br /></span></b><b><span style="font-family:Arial;">Huggins: </span></b></span><span style=";font-family:Arial;font-size:10;" ><span style="font-size:100%;">Well, one of the biggest drawbacks with user interface testing tools is that they're slow for various reasons. One way to bring the test run times down is to run them in parallel on a grid of servers, instead of sequentially. Of course, that isn't news to your average Googler. Engineers would be more likely to run automated browser UI tests if they could run 1000 tests in 1 minute total time on 1000 machines instead of 1000 tests in 1000 minutes on 1 machine. Sadly, though, most projects allocate only one machine, maybe two, to browser testing. I'm really excited to come to Google with the resources, the corporate interest, and the internal client base to make a large scale Selenium UI test farm possible. Eventually, I&#8217;d like to take Selenium in some new directions that we&#8217;ll talk about in later blog posts. But I'm getting ahead of myself. I have to survive Noogler training first.</span> <o:p></o:p></span></p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <span style="font-size:100%;"><span style="font-family:arial;">Posted by Patrick Copeland, Test Engineering Director<br /></span><br /><a href="//picasaweb.google.com/TestEngTeam/CodeGreen/photo?authkey=IA66TjDvtik#5112064269199230642"><img src="//lh6.google.com/TestEngTeam/RvGzXjKWRrI/AAAAAAAAADg/6n6WPe50yJQ/s400/big_logo.jpg"></a><br /></span><span style=";font-family:Arial;font-size:100%;color:green;" >We thought you might be interested in some articles from our internal monthly testing newsletter called CODE GREEN...<br /><br />Many projects at Google have started using or are considering using Selenium. We recently interviewed Noogler (new people to Google) Jason Huggins, who is the creator and developer of <a href="http://www.openqa.org/selenium/" target="_blank"><span style="color:green;">Selenium</span></a>, to learn about how it all started and where it's going. <o:p></o:p></span> <p><span style=";font-family:Arial;font-size:100%;color:green;" >[Side note: Even before his first day at the Googleplex, Jason showed an amazing dedication to Google. After leaving <st1:city st="on"><st1:place st="on">Chicago</st1:place></st1:city> with the big moving truck, he and his family had to stop after just a few hours because of an ice storm. Cars sliding off the road left and right. Further along, in <st1:state st="on"><st1:place st="on">Kansas</st1:place></st1:state>, one of his kids caught pneumonia. His family stayed in the local hospital while Jason drove on. Heading west, there was a big snow storm in <st1:state st="on"><st1:place st="on">Colorado</st1:place></st1:state>, which he wanted to avoid. He drove further south and ended up in a rare (but really real) <a href="http://earthobservatory.nasa.gov/NaturalHazards/natural_hazards_v2.php3?img_id=14141" target="_blank"><span style="text-decoration: none;color:green;" >dust storm over the Border States</span></a>. He promised us some great video footage of his drive through tumbleweeds. He finally arrived and has settled in and is looking forward to calmer times in the Bay Area. After that trip, he isn't even worried about earthquakes, fires, mud slides, or traffic on the 101.]</span></p><p><span style="font-family: arial;font-size:100%;" >Couple of GTAC Videos with Jason: <a href="//youtube.com/watch?v=qxBatJ1N_Og">SeleniumRC</a></span><span style="font-size:100%;"><span style="font-family: arial;">, </span><a style="font-family: arial;" href="//youtube.com/watch?v=Vlz-WmcrBL8">Selenium vs WebDriver</a></span><br /><span style=";font-family:Arial;font-size:100%;color:green;" ><o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: Why did you invent Selenium? What was the motivation? </span></b></span><span style=";font-family:Arial;font-size:100%;" ><br /><b>Huggins:</b> Selenium was extracted from a web-based (Python + Plone!) time-and-expense (T&amp;E) application my team and I were building for my previous employer. One of the mandates for the new T&amp;E app was that it needed to be "fast, fast, fast." The legacy application was a client-server Lotus Notes application and wasn't scalable to the current number of offices and employees at the time. To live up to the "fast, fast, fast" design goal, we tried to improve and speed up the user experience as much as possible. For example, expense reports can get pretty long for people who travel a lot. No matter how many default rows we put in a blank expense form, people often needed to add more rows of expense items to their reports. So we added an "Add row" button to the expense report form. To make this "fast, fast, fast," I decided to use a button that triggered JavaScript to dynamically add one blank row to the form. At the time (Spring 2004), however, JavaScript was considered buggy and evil by most web developers, so I caught a lot of flak for not going with the classic approach of POSTing the form and triggering a complete page refresh with the current form data, plus one blank row.<o:p></o:p></span></p> <p><span style=";font-family:Arial;font-size:100%;" >Going down the road of using JavaScript had consequences. For one, we had a really, really difficult time testing that little "Add row" button. And sadly, it broke often. One week "Add row" would be working in Mozilla (Firefox was pre-1.0), but broken in Internet Explorer. And of course, nothing was working in Safari since few developers were allowed to have Macs. ;-) The following week, we'd open a bug saying "'Add row' is broken in IE!!" The developer assigned to the issue would fix and test it in IE, but not test for regressions in Mozilla. So, "Add row" would now be broken in Mozilla, and I'd have to open a ticket saying "'Add row' is now broken in Mozilla!!!". Unlike most other corporate IT shops, we didn't have the luxury of telling all employees to use a single browser, and developers didn't want to manually test every feature in all supported browsers every time. Also, we had a very tiny budget and commercial testing tools were -- and still are -- ridiculously over-priced on a per-seat basis. The T&amp;E project was done the "<st1:street st="on"><st1:address st="on">Agile Way</st1:address></st1:street>" -- every developer does testing -- so shelling out thousands of dollars per developer for a testing tool wasn't going to happen. Never mind the fact that there were no commercial tools that did what we needed anyway!<o:p></o:p></span></p> <p><span style=";font-family:Arial;font-size:100%;" >After many months of trial and error and various code workarounds, I came to the conclusion I needed a testing tool that would let me functional-test JavaScript-enhanced web user interfaces (aka "DHTML" or now "<st1:city st="on"><st1:place st="on">Ajax</st1:place></st1:city>"). More specifically, I needed to test the browser UIs: Internet Explorer, Mozilla Firefox, and Safari. There were no commercial apps at the time that could do this, and the only open source option was JsUnit, which was more focused on unit testing pure JavaScript functions, rather than being a higher-level black-box/smoke-test walk through a web app. So we needed to write our own tool. Our first attempt was a Mozilla extension called "driftwood" (never <span style="font-size:100%;">released), coded by Andrew McCormick, another co-worker of mine at the time. It did make testing the "Add row" button possible, but since it was Mozilla-only, it wasn't what we needed for testing in all browsers. Paul Gross and I started over, and I started to educate myself on functional testing tools and techniques and stumbled upon Ward Cunningham's Framework for Integrated Testing (FIT). I originally set out to implement "FIT for JavaScript," but quickly realized we were drifting away from the FIT API, so Selenium became its own thing.</span></span><span style=";font-family:Arial;font-size:100%;" ><o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: Why does the world need another test tool?</span></b><b><span style="font-family:Arial;"><br />Huggins: </span></b></span><span style=";font-family:Arial;font-size:100%;" >At the time I created Selenium, had there been another testing tool that could test JavaScript UI features in all browsers on all platforms, believe me, I would have saved lots of time *not* writing my own tool.<o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: What's special about it?</span></b></span><span style=";font-family:Arial;font-size:100%;" ><br /><b>Huggins:</b> Well, maybe the right question is "What's &#8220;lucky&#8221; about it? Selenium was created in a time when JavaScript was considered "bad" and generally avoided by most professional web developers. Then Google Maps hit the scene a year later, the term "<st1:city st="on"><st1:place st="on">Ajax</st1:place></st1:city>" was coined, and BOOM! Overnight, JavaScript became "good." Also, Firefox started stealing market share from IE. The combination of needing to test 1) JavaScript features 2) in several browsers (not just IE) was a "right place, right time" moment for Selenium.<o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: When did you realize that Selenium was a big deal? What was the tipping point? </span></b></span><span style=";font-family:Arial;font-size:100%;" ><br /><b>Huggins: </b>When I started being asked to give presentations or write about Selenium by people I didn't know. The tipping point for Selenium technically relied on two things: 1) the Selenium IDE for Firefox, written by Shinya Kasatani, which made installation and the first-hour experience tons better for new users. And 2), Selenium Remote Control (RC) created by Paul Hammant, and extended by Dan Fabulich, Nelson Sproul, and Patrick Lightbody, which let developers write their tests in Java, C#, Perl, Python, or Ruby, and not have to write all their tests in the original FIT-like HTML tables. Socially, if Google Maps or Gmail never existed and thus the whole Ajax gold rush, I wonder if JavaScript would still be considered "bad," with a similar "why bother?" attitude to testing it. <o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: Have you discovered any interesting teams using Selenium in ways you'd never intended? </span></b></span><span style=";font-family:Arial;font-size:100%;" ><br /><b>Huggins:</b> At my previous company, I did see some developers write Selenium scripts to create their time and expense reports for them from YAML or XLS files. Since we hadn't exposed a back-end API, automating the browser for data entry was the next best thing. It was never designed for this purpose, but I started (ab)using it as coded bug reports. Asking users for steps on how to reproduce a bug naturally lends itself to looking like a Selenium test for that bug. Also, I've used the Selenium IDE Firefox plug-in to enter NBC's "Deal or No Deal" contest on their website from home, but I stopped doing that when I read in the fine print that the use of automation tools to enter their contest was grounds for disqualification. <o:p></o:p></span></p> <p><span style="font-size:100%;"><b><span style=";font-family:Arial;color:green;" >CG: What advice do you have to offer Google groups interested in Selenium?<br /></span></b><b><span style="font-family:Arial;">Huggins: </span></b></span><span style=";font-family:Arial;font-size:10;" ><span style="font-size:100%;">Well, one of the biggest drawbacks with user interface testing tools is that they're slow for various reasons. One way to bring the test run times down is to run them in parallel on a grid of servers, instead of sequentially. Of course, that isn't news to your average Googler. Engineers would be more likely to run automated browser UI tests if they could run 1000 tests in 1 minute total time on 1000 machines instead of 1000 tests in 1000 minutes on 1 machine. Sadly, though, most projects allocate only one machine, maybe two, to browser testing. I'm really excited to come to Google with the resources, the corporate interest, and the internal client base to make a large scale Selenium UI test farm possible. Eventually, I&#8217;d like to take Selenium in some new directions that we&#8217;ll talk about in later blog posts. But I'm getting ahead of myself. I have to survive Noogler training first.</span> <o:p></o:p></span></p> <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:Selenium&#39;s Inventor&url=https://testing.googleblog.com/2007/09/seleniums-inventor.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/2007/09/seleniums-inventor.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/09/seleniums-inventor.html#comments' style='font-weight: 500; text-decoration: underline;'>22 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/09/seleniums-inventor.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/Jason%20Huggins' rel='tag'> Jason Huggins </a> , <a class='label' href='https://testing.googleblog.com/search/label/Patrick%20Copeland' rel='tag'> Patrick Copeland </a> </span> </div> </div> </div> <div class='post' data-id='5925885731388231027' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/09/testing-applications-and-apis.html' itemprop='url' title='Testing Applications and APIs'> Testing Applications and APIs </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Friday, September 14, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <p style="font-family:arial;"><span style="font-size:100%;">Posted by <span class="HcCDpe">George <span class="blsp-spelling-error" id="SPELLING_ERROR_0">Pirocanac</span></span>, Test Engineering Manager<br /><br />Earlier Blog entries described the strategy and methodology for testing the functionality of various kinds of applications. The basic approach is to isolate the logic of the application from the external <span class="blsp-spelling-error" id="SPELLING_ERROR_1">API</span> calls that the application makes through the use of various constructs called mocks, fakes, dummy routines, etc. Depending on how the application is designed and written, this can lead to smaller, simpler tests that cover more, execute more quickly, and lead to quicker diagnosis of problems than the larger end-to-end or system tests. On the other hand, they are not a complete replacement for end-to-end testing. By their very nature, the small tests don't test the assumptions and interactions between the application and the <span class="blsp-spelling-error" id="SPELLING_ERROR_2">APIs</span> that it calls. As a result, a diversified application testing strategy includes small, medium, and large tests. (See <a href="//youtube.com/watch?v=pDtfMYyaTQY">Copeland&#8217;s <span class="blsp-spelling-error" id="SPELLING_ERROR_3">GTAC</span> Video</a>, fast forward about 5 minutes in to hear a brief description of developer testing and small, medium, large) <o:p></o:p></span></p> <p style="font-family:arial;"><span style="font-size:100%;">What about testing the <span class="blsp-spelling-error" id="SPELLING_ERROR_4">APIs</span> themselves? What if anything is different? The first approach mirrors the small test approach. Each of the <span class="blsp-spelling-error" id="SPELLING_ERROR_5">API</span> calls is exercised with a variety of inputs and the outputs that are verified according to the specification. For isolated, stateless <span class="blsp-spelling-error" id="SPELLING_ERROR_6">APIs</span> (math library functions come to mind), this can be very effective by itself. However, many <span class="blsp-spelling-error" id="SPELLING_ERROR_7">APIs</span> are not isolated or stateless, and their results can vary according to the *combinations* of calls that were made. One way to deal with this is to analyze the dependencies between the calls and create mini-applications to exercise and verify these combinations of calls. Often, this falls into the so-called typical usage patterns or user scenarios. While good, this first approach only gives us limited confidence. We also need to test what happens when not-so-typical sets of calls are made as well. Often application writers introduce usage patterns that the spec didn't anticipate. <o:p></o:p></span></p> <p style="font-family:arial;"><span style="font-size:100%;">Another approach is to capture the <span class="blsp-spelling-error" id="SPELLING_ERROR_8">API</span> calls made by real applications under controlled situations and then replay only the calls under the same controlled situations. These types of tests fall into the medium category. Again, the idea is to test series and combinations of calls, but the difficulty can lie in recreating the exact environment. In addition, this approach is vulnerable to building tests that traverse the same paths in the code. Adding fuzz to the parameters and call patterns can help, but not eliminate, this problem. <o:p></o:p></span></p> <p style="font-family:arial;"><span style="font-size:100%;">The third approach is to pull out the big hammer. Does it make sense to test the <span class="blsp-spelling-error" id="SPELLING_ERROR_9">APIs</span> with large applications? After all, if something goes wrong, you have to have specific knowledge about the application to triage the problem. You also have to be familiar with the techniques in testing the application. Testing a map-based application can be quite different from a calendar-based one, even if they share a common subset of <span class="blsp-spelling-error" id="SPELLING_ERROR_10">APIs</span>. The strongest case for testing <span class="blsp-spelling-error" id="SPELLING_ERROR_11">APIs</span> with large applications is compatibility testing. <span class="blsp-spelling-error" id="SPELLING_ERROR_12">APIs</span> not only have to return correct results, but they have to do it in the same manner from revision to revision. It's a sort of contract between the <span class="blsp-spelling-error" id="SPELLING_ERROR_13">API</span> writer and the application writer. When the <span class="blsp-spelling-error" id="SPELLING_ERROR_14">API</span> is private, then only a relative small number of parties have to agree on a change to the contract, but when it is public, even a small change can break a lot of applications. <o:p></o:p></span></p> <p class="MsoNormal"><span style=";font-family:arial;font-size:100%;" >So when it comes to <span class="blsp-spelling-error" id="SPELLING_ERROR_15">API</span> testing, it seems we are back to small, medium, and large approaches after all. Just as in application testing where you can't completely divorce the <span class="blsp-spelling-error" id="SPELLING_ERROR_16">API</span> from the application, we cannot completely divorce the application from <span class="blsp-spelling-error" id="SPELLING_ERROR_17">API</span> testing. </span> <o:p></o:p></p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <p style="font-family:arial;"><span style="font-size:100%;">Posted by <span class="HcCDpe">George <span class="blsp-spelling-error" id="SPELLING_ERROR_0">Pirocanac</span></span>, Test Engineering Manager<br /><br />Earlier Blog entries described the strategy and methodology for testing the functionality of various kinds of applications. The basic approach is to isolate the logic of the application from the external <span class="blsp-spelling-error" id="SPELLING_ERROR_1">API</span> calls that the application makes through the use of various constructs called mocks, fakes, dummy routines, etc. Depending on how the application is designed and written, this can lead to smaller, simpler tests that cover more, execute more quickly, and lead to quicker diagnosis of problems than the larger end-to-end or system tests. On the other hand, they are not a complete replacement for end-to-end testing. By their very nature, the small tests don't test the assumptions and interactions between the application and the <span class="blsp-spelling-error" id="SPELLING_ERROR_2">APIs</span> that it calls. As a result, a diversified application testing strategy includes small, medium, and large tests. (See <a href="//youtube.com/watch?v=pDtfMYyaTQY">Copeland&#8217;s <span class="blsp-spelling-error" id="SPELLING_ERROR_3">GTAC</span> Video</a>, fast forward about 5 minutes in to hear a brief description of developer testing and small, medium, large) <o:p></o:p></span></p> <p style="font-family:arial;"><span style="font-size:100%;">What about testing the <span class="blsp-spelling-error" id="SPELLING_ERROR_4">APIs</span> themselves? What if anything is different? The first approach mirrors the small test approach. Each of the <span class="blsp-spelling-error" id="SPELLING_ERROR_5">API</span> calls is exercised with a variety of inputs and the outputs that are verified according to the specification. For isolated, stateless <span class="blsp-spelling-error" id="SPELLING_ERROR_6">APIs</span> (math library functions come to mind), this can be very effective by itself. However, many <span class="blsp-spelling-error" id="SPELLING_ERROR_7">APIs</span> are not isolated or stateless, and their results can vary according to the *combinations* of calls that were made. One way to deal with this is to analyze the dependencies between the calls and create mini-applications to exercise and verify these combinations of calls. Often, this falls into the so-called typical usage patterns or user scenarios. While good, this first approach only gives us limited confidence. We also need to test what happens when not-so-typical sets of calls are made as well. Often application writers introduce usage patterns that the spec didn't anticipate. <o:p></o:p></span></p> <p style="font-family:arial;"><span style="font-size:100%;">Another approach is to capture the <span class="blsp-spelling-error" id="SPELLING_ERROR_8">API</span> calls made by real applications under controlled situations and then replay only the calls under the same controlled situations. These types of tests fall into the medium category. Again, the idea is to test series and combinations of calls, but the difficulty can lie in recreating the exact environment. In addition, this approach is vulnerable to building tests that traverse the same paths in the code. Adding fuzz to the parameters and call patterns can help, but not eliminate, this problem. <o:p></o:p></span></p> <p style="font-family:arial;"><span style="font-size:100%;">The third approach is to pull out the big hammer. Does it make sense to test the <span class="blsp-spelling-error" id="SPELLING_ERROR_9">APIs</span> with large applications? After all, if something goes wrong, you have to have specific knowledge about the application to triage the problem. You also have to be familiar with the techniques in testing the application. Testing a map-based application can be quite different from a calendar-based one, even if they share a common subset of <span class="blsp-spelling-error" id="SPELLING_ERROR_10">APIs</span>. The strongest case for testing <span class="blsp-spelling-error" id="SPELLING_ERROR_11">APIs</span> with large applications is compatibility testing. <span class="blsp-spelling-error" id="SPELLING_ERROR_12">APIs</span> not only have to return correct results, but they have to do it in the same manner from revision to revision. It's a sort of contract between the <span class="blsp-spelling-error" id="SPELLING_ERROR_13">API</span> writer and the application writer. When the <span class="blsp-spelling-error" id="SPELLING_ERROR_14">API</span> is private, then only a relative small number of parties have to agree on a change to the contract, but when it is public, even a small change can break a lot of applications. <o:p></o:p></span></p> <p class="MsoNormal"><span style=";font-family:arial;font-size:100%;" >So when it comes to <span class="blsp-spelling-error" id="SPELLING_ERROR_15">API</span> testing, it seems we are back to small, medium, and large approaches after all. Just as in application testing where you can't completely divorce the <span class="blsp-spelling-error" id="SPELLING_ERROR_16">API</span> from the application, we cannot completely divorce the application from <span class="blsp-spelling-error" id="SPELLING_ERROR_17">API</span> testing. </span> <o:p></o:p></p> <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 Applications and APIs&url=https://testing.googleblog.com/2007/09/testing-applications-and-apis.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/2007/09/testing-applications-and-apis.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/09/testing-applications-and-apis.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/2007/09/testing-applications-and-apis.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/George%20Pirocanac' rel='tag'> George Pirocanac </a> </span> </div> </div> </div> <div class='post' data-id='6629947471058147239' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/09/university-of-arizona-tech-talk.html' itemprop='url' title='University of Arizona Tech Talk'> University of Arizona Tech Talk </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Wednesday, September 12, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <p class="MsoNormal">Posted by Patrick Copeland, Test Engineering Director</p><p class="MsoNormal">I visited the <st1:place st="on"><st1:placetype st="on">University</st1:placetype> of <st1:placename st="on">Arizona</st1:placename></st1:place> last night, along with several <span class="blsp-spelling-error" id="SPELLING_ERROR_0"><span class="blsp-spelling-error" id="SPELLING_ERROR_0">Googlers</span></span>, as part of a series of Tech Talks being given at selected schools. The talk was about <a style="border-bottom-style: groove;" href="http://labs.google.com/papers/gfs.html"><span class="blsp-spelling-error" id="SPELLING_ERROR_1"><span class="blsp-spelling-error" id="SPELLING_ERROR_1">GFS</span></span></a> (Google File System). The auditorium was standing room only, with a turn out of over 150 computer science and computer engineering students (probably enticed with the free pizza and t-shirts :^). We really appreciated the turn out and the enthusiasm for Google. The questions following the talk were great and we probably could have gone on for several hours.<span style=""> </span>I had a chance to talk to a few folks afterwards about their projects ranging from security research, to traffic simulation. I also met one of the professors and discussed the potential of doing some joint research.</p> <p class="MsoNormal">During the trip I also visited my grandmother who lives in <st1:city st="on"><st1:place st="on">Tucson</st1:place></st1:city>. I was showing her a picture of my son on a <span class="blsp-spelling-error" id="SPELLING_ERROR_2"><span class="blsp-spelling-error" id="SPELLING_ERROR_2">BlackBerry</span></span>. She was fascinated and asked me how it worked. I started to think about how to explain it and in that moment, it humbled me to think about the number of complex systems employed to do such a simple thing. Displaying a photo from a web page includes device side operating systems, run time languages, cell technology, network stacks, cell receivers, routers, serving front and back-ends,&#8230;and more. An interesting side note: the bits for my <span class="blsp-spelling-error" id="SPELLING_ERROR_3"><span class="blsp-spelling-error" id="SPELLING_ERROR_3">jpg</span></span> file ultimately get stored at Google in <span class="blsp-spelling-error" id="SPELLING_ERROR_4"><span class="blsp-spelling-error" id="SPELLING_ERROR_4">GFS</span></span>, the topic of my talk that night. Obviously, each part of that chain is complex and important to get my simple scenario to work. I started to explain it in plain language and she quickly stopped me and said that when she was a child her family had a crank operated &#8220;party-line&#8221; phone, where multiple families shared a single line. What hit me was that even though technology has gotten more complex, the types of scenarios we are enabling are still very basic and human: communicating, sharing, and connecting people. Even with all of the automated testing that we do, deep testing done from the perspective of customers is still absolutely critical.<br /></p> <p class="MsoNormal">Again, thanks to the students at the <st1:place st="on"><st1:placetype st="on">University</st1:placetype> of <st1:placename st="on">Arizona</st1:placename></st1:place>. Bear Down! We&#8217;re looking forward to visiting all of the schools on our list this season. </p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <p class="MsoNormal">Posted by Patrick Copeland, Test Engineering Director</p><p class="MsoNormal">I visited the <st1:place st="on"><st1:placetype st="on">University</st1:placetype> of <st1:placename st="on">Arizona</st1:placename></st1:place> last night, along with several <span class="blsp-spelling-error" id="SPELLING_ERROR_0"><span class="blsp-spelling-error" id="SPELLING_ERROR_0">Googlers</span></span>, as part of a series of Tech Talks being given at selected schools. The talk was about <a style="border-bottom-style: groove;" href="http://labs.google.com/papers/gfs.html"><span class="blsp-spelling-error" id="SPELLING_ERROR_1"><span class="blsp-spelling-error" id="SPELLING_ERROR_1">GFS</span></span></a> (Google File System). The auditorium was standing room only, with a turn out of over 150 computer science and computer engineering students (probably enticed with the free pizza and t-shirts :^). We really appreciated the turn out and the enthusiasm for Google. The questions following the talk were great and we probably could have gone on for several hours.<span style=""> </span>I had a chance to talk to a few folks afterwards about their projects ranging from security research, to traffic simulation. I also met one of the professors and discussed the potential of doing some joint research.</p> <p class="MsoNormal">During the trip I also visited my grandmother who lives in <st1:city st="on"><st1:place st="on">Tucson</st1:place></st1:city>. I was showing her a picture of my son on a <span class="blsp-spelling-error" id="SPELLING_ERROR_2"><span class="blsp-spelling-error" id="SPELLING_ERROR_2">BlackBerry</span></span>. She was fascinated and asked me how it worked. I started to think about how to explain it and in that moment, it humbled me to think about the number of complex systems employed to do such a simple thing. Displaying a photo from a web page includes device side operating systems, run time languages, cell technology, network stacks, cell receivers, routers, serving front and back-ends,&#8230;and more. An interesting side note: the bits for my <span class="blsp-spelling-error" id="SPELLING_ERROR_3"><span class="blsp-spelling-error" id="SPELLING_ERROR_3">jpg</span></span> file ultimately get stored at Google in <span class="blsp-spelling-error" id="SPELLING_ERROR_4"><span class="blsp-spelling-error" id="SPELLING_ERROR_4">GFS</span></span>, the topic of my talk that night. Obviously, each part of that chain is complex and important to get my simple scenario to work. I started to explain it in plain language and she quickly stopped me and said that when she was a child her family had a crank operated &#8220;party-line&#8221; phone, where multiple families shared a single line. What hit me was that even though technology has gotten more complex, the types of scenarios we are enabling are still very basic and human: communicating, sharing, and connecting people. Even with all of the automated testing that we do, deep testing done from the perspective of customers is still absolutely critical.<br /></p> <p class="MsoNormal">Again, thanks to the students at the <st1:place st="on"><st1:placetype st="on">University</st1:placetype> of <st1:placename st="on">Arizona</st1:placename></st1:place>. Bear Down! We&#8217;re looking forward to visiting all of the schools on our list this season. </p> <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:University of Arizona Tech Talk&url=https://testing.googleblog.com/2007/09/university-of-arizona-tech-talk.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/2007/09/university-of-arizona-tech-talk.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/09/university-of-arizona-tech-talk.html#comments' style='font-weight: 500; text-decoration: underline;'>2 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/09/university-of-arizona-tech-talk.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/Patrick%20Copeland' rel='tag'> Patrick Copeland </a> </span> </div> </div> </div> <div class='post' data-id='5142915666893582028' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/09/more-feedback-from-google-interns.html' itemprop='url' title='More feedback from Google Interns'> More feedback from Google Interns </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Thursday, September 06, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <p class="MsoNormal" style="margin-bottom: 12pt; font-family: arial;">Posted by Patrick Copeland, Test Engineering Director</p> <p class="MsoNormal" style="margin-bottom: 12pt; font-family: arial;">Here's some unsolicited feedback from Kurt Kluever who ended up on his school's <a href="//picasaweb.google.com/TestEngTeam/Interns/photo#5107492655286707234">web page</a> (Rochester Institute of Technology). While he was at Google this summer he tested JotSpot. Kurt's project included enhancing a Selenium Framework for testing JotSpot. He add automated tests to an existing suite and refactored code to allow the framework to be more extensible. In addition, he fixed several issues with Selenium RC that allows for better concurrent execution of tests within a browser&#8217;s object model. The scope of the project was focused on one application, but he looked through code from various other projects and applied the design patterns to the JotSpot framework.<br /></p><p class="MsoNormal" style="margin-bottom: 12pt;"><span style="font-family:arial;">His experience in his own words&#8230;</span><a style="font-family: arial;" href="http://www.rit.edu/%7E964www/student/stu_alum_pdfs/KurtKlueverCoop.pdf">link to RIT site pdf</a><span style="font-family:arial;">.</span><o:p></o:p></p> <span style=";font-family:Arial;font-size:12;" ><br /></span><o:p></o:p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <p class="MsoNormal" style="margin-bottom: 12pt; font-family: arial;">Posted by Patrick Copeland, Test Engineering Director</p> <p class="MsoNormal" style="margin-bottom: 12pt; font-family: arial;">Here's some unsolicited feedback from Kurt Kluever who ended up on his school's <a href="//picasaweb.google.com/TestEngTeam/Interns/photo#5107492655286707234">web page</a> (Rochester Institute of Technology). While he was at Google this summer he tested JotSpot. Kurt's project included enhancing a Selenium Framework for testing JotSpot. He add automated tests to an existing suite and refactored code to allow the framework to be more extensible. In addition, he fixed several issues with Selenium RC that allows for better concurrent execution of tests within a browser&#8217;s object model. The scope of the project was focused on one application, but he looked through code from various other projects and applied the design patterns to the JotSpot framework.<br /></p><p class="MsoNormal" style="margin-bottom: 12pt;"><span style="font-family:arial;">His experience in his own words&#8230;</span><a style="font-family: arial;" href="http://www.rit.edu/%7E964www/student/stu_alum_pdfs/KurtKlueverCoop.pdf">link to RIT site pdf</a><span style="font-family:arial;">.</span><o:p></o:p></p> <span style=";font-family:Arial;font-size:12;" ><br /></span><o:p></o:p> <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:More feedback from Google Interns&url=https://testing.googleblog.com/2007/09/more-feedback-from-google-interns.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/2007/09/more-feedback-from-google-interns.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/09/more-feedback-from-google-interns.html#comments' style='font-weight: 500; text-decoration: underline;'>No comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/09/more-feedback-from-google-interns.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/Patrick%20Copeland' rel='tag'> Patrick Copeland </a> </span> </div> </div> </div> <div class='post' data-id='5508199163506532899' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/08/gtac-videos-now-online.html' itemprop='url' title='GTAC videos now online'> GTAC videos now online </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Tuesday, August 28, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by Allen Hutchison, Engineering Manager<br /><br />We finished up the second annual <a title="Google Test Automation Conference" href="http://googletesting.blogspot.com/search/label/GTAC" id="hggr">Google Test Automation Conference</a> on Saturday with a boat cruise around Manhattan. There's still a lot of work for us to do to wrap up all the loose ends, but one that we have gotten to right away is posting the videos on <a title="YouTube" href="//www.youtube.com/view_play_list?p=7D3E685B59779C16" id="t6hs">YouTube</a>.<br /><br /><object height="370" width="530"><param name="movie" value="//www.youtube.com/p/7D3E685B59779C16"></param><embed src="//www.youtube.com/p/7D3E685B59779C16" type="application/x-shockwave-flash" width="530" height="370"></embed></object><br /><br />We hope that you enjoy the videos, and we'd like you to join everyone already conversing on our <a title="Google Group" href="http://groups.google.com/group/ltac" id="bn45">Google Group</a>. Several people have posted their reviews of the conference; you can find them in the comments on the <a title="GTAC Community Thread" href="http://googletesting.blogspot.com/2007/08/gtac-community-thread.html" id="jucz">GTAC Community Thread</a>, or through a <a title="blog search for GTAC" href="http://blogsearch.google.com/blogsearch?hl=en&q=GTAC&amp;btnG=Search+Blogs" id="ocdl">blog search for GTAC</a>. Finally, our team posted several conference photos on <a title="Picasa Web Albums" href="//picasaweb.google.com/NYC1119thave/TheSecondAnnualGoogleTestAutomationConference" id="ej:i">Picasa Web Albums</a>. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by Allen Hutchison, Engineering Manager<br /><br />We finished up the second annual <a title="Google Test Automation Conference" href="http://googletesting.blogspot.com/search/label/GTAC" id="hggr">Google Test Automation Conference</a> on Saturday with a boat cruise around Manhattan. There's still a lot of work for us to do to wrap up all the loose ends, but one that we have gotten to right away is posting the videos on <a title="YouTube" href="//www.youtube.com/view_play_list?p=7D3E685B59779C16" id="t6hs">YouTube</a>.<br /><br /><object height="370" width="530"><param name="movie" value="//www.youtube.com/p/7D3E685B59779C16"></param><embed src="//www.youtube.com/p/7D3E685B59779C16" type="application/x-shockwave-flash" width="530" height="370"></embed></object><br /><br />We hope that you enjoy the videos, and we'd like you to join everyone already conversing on our <a title="Google Group" href="http://groups.google.com/group/ltac" id="bn45">Google Group</a>. Several people have posted their reviews of the conference; you can find them in the comments on the <a title="GTAC Community Thread" href="http://googletesting.blogspot.com/2007/08/gtac-community-thread.html" id="jucz">GTAC Community Thread</a>, or through a <a title="blog search for GTAC" href="http://blogsearch.google.com/blogsearch?hl=en&q=GTAC&amp;btnG=Search+Blogs" id="ocdl">blog search for GTAC</a>. Finally, our team posted several conference photos on <a title="Picasa Web Albums" href="//picasaweb.google.com/NYC1119thave/TheSecondAnnualGoogleTestAutomationConference" id="ej:i">Picasa Web Albums</a>. <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:GTAC videos now online&url=https://testing.googleblog.com/2007/08/gtac-videos-now-online.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/2007/08/gtac-videos-now-online.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/08/gtac-videos-now-online.html#comments' style='font-weight: 500; text-decoration: underline;'>9 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/08/gtac-videos-now-online.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='4966946268104103025' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/08/gtac-community-thread.html' itemprop='url' title='GTAC Community Thread'> GTAC Community Thread </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Thursday, August 23, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by Allen Hutchison, Engineering Manager<br /><br />We're moments away from the beginning of the <a title="Google Test Automation Conference" href="http://googletesting.blogspot.com/search/label/GTAC" id="v6s.">Google Test Automation Conference</a>. If you are attending in person, then I'll see you shortly. If you plan to watch the videos on <a title="YouTube" href="//www.youtube.com/user/google" id="ov3s">YouTube</a>, then keep an eye on this space. We'll be posting links to the talk videos throughout the next few days. The conference isn't just about the talks, though: this is a community conference. So use the comment space on this post to point people to your GTAC Live Blog, your pictures from the conference, and your thoughts about the conference.<br /><br />We also have a <a title="Google Group" href="http://groups.google.com/group/ltac" id="nbc1">Google Group</a> set aside for discussion about the conference and test automation. There are several people there from past conferences as well as this one. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by Allen Hutchison, Engineering Manager<br /><br />We're moments away from the beginning of the <a title="Google Test Automation Conference" href="http://googletesting.blogspot.com/search/label/GTAC" id="v6s.">Google Test Automation Conference</a>. If you are attending in person, then I'll see you shortly. If you plan to watch the videos on <a title="YouTube" href="//www.youtube.com/user/google" id="ov3s">YouTube</a>, then keep an eye on this space. We'll be posting links to the talk videos throughout the next few days. The conference isn't just about the talks, though: this is a community conference. So use the comment space on this post to point people to your GTAC Live Blog, your pictures from the conference, and your thoughts about the conference.<br /><br />We also have a <a title="Google Group" href="http://groups.google.com/group/ltac" id="nbc1">Google Group</a> set aside for discussion about the conference and test automation. There are several people there from past conferences as well as this one. <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:GTAC Community Thread&url=https://testing.googleblog.com/2007/08/gtac-community-thread.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/2007/08/gtac-community-thread.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/08/gtac-community-thread.html#comments' style='font-weight: 500; text-decoration: underline;'>29 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/08/gtac-community-thread.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='1213952299157306742' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/08/abduls-summer-intern-testimonial.html' itemprop='url' title='Abdul&#39;s Summer Intern Testimonial'> Abdul's Summer Intern Testimonial </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Wednesday, August 15, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <span style="font-family:arial;">Posted by Patrick Copeland, Test Engineering Director<br /><br />With intern season coming to a close, we wanted to share a testimonial from one of the 90 interns who joined us in Test Engineering this summer. This one is from a Software Engineer in Test who worked in the NYC office on the "blog search" project...</span><br /><br /><span style="font-family:arial;">Interning as a Software Engineering Tester for Google was certainly an experience I won't forget. It started three weeks before the end of my summer break, when I received an email from a recruiter in Google's New York City office requesting an interview for a Fall internship position. I had not planned for this, but I figured I would give it a shot! Three weeks and a few interviews later, I was in New York City, apartment-shopping for my internship, which started the following week! Having never worked in test engineering before, I wasn't quite sure what to expect. All I knew was Google works fast! I hoped I could keep up.</span><span class="q" style="font-family:arial;"><br /><br />The first couple of weeks at Google required the most adjustment. While diving into my project's code and "Noogler" (new Googler) training courses, I came to the realization that this was going to be one of the most challenging experiences of my life. In the past, I've always associated challenging experiences with stress. But this was beginning to feel quite the opposite. Everyone around me was incredibly helpful, and the facilities were so comfortable that I actually found myself enjoying the challenge to the point of not wanting to leave work. The opportunity to learn at Google is literally endless, and I couldn't get enough.<br /><br />The great thing about test engineering is the ability to pick the challenges you want to attack. You get to find problems and attack code from angles that you never thought of before. The more you work and the more you test, the more you find out the RIGHT way of doing things, and just when you think you've got it perfect, you find a new way of optimizing your project's code. The product is as good as your testing proves it to be, and in a sense you become the gatekeeper for a product that is being used by millions worldwide. Having that responsibility is an amazing feeling. </span><span style="font-family:arial;"><br /><br />There were many projects available for me to work on at Google. From a test engineer's standpoint, there is always room for improvement in any product. I started my internship working on the back-end crawling and indexing components of Blog Search. After a few weeks of studying RSS technology and looking through Blog Search's parsing and indexing approach, the testing team and I were able to formulate a formal test plan that addressed potential security vulnerabilities and potential avenues for failure in many special case scenarios. Our code analysis and test cases will be constantly revisited and extended at every code change and will be the basis of many design decisions through the life of Blog Search. As my internship continued, I had the opportunity to work on several other projects, from small, new projects to larger, more established ones. I personally preferred the newer projects. I enjoy being involved from the beginning and being able to sit side-by-side with project managers and technical leads and give feedback about issues in the latest development. <br /><br />What's really fun is that every week, the entire NYC test engineering team gets together to sync up, share ideas, communicate issues, and share the latest news. This is where some of the great ideas get drawn up, and when something good hits the table, we pick it up and run with it! In my last few weeks at Google, we were able to draw a correlation between some common issues that we were all facing and identify the underlying challenges that needed to be addressed. Immediately, we started work on an automated testing framework that would solve most of our problems. When finished, it will be used not only by us, but possibly by every project team within Google.<br /><br />Overall, working at Google was a great experience. I had my share of fun, and I learned a great deal and am very grateful for the experience.</span> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <span style="font-family:arial;">Posted by Patrick Copeland, Test Engineering Director<br /><br />With intern season coming to a close, we wanted to share a testimonial from one of the 90 interns who joined us in Test Engineering this summer. This one is from a Software Engineer in Test who worked in the NYC office on the "blog search" project...</span><br /><br /><span style="font-family:arial;">Interning as a Software Engineering Tester for Google was certainly an experience I won't forget. It started three weeks before the end of my summer break, when I received an email from a recruiter in Google's New York City office requesting an interview for a Fall internship position. I had not planned for this, but I figured I would give it a shot! Three weeks and a few interviews later, I was in New York City, apartment-shopping for my internship, which started the following week! Having never worked in test engineering before, I wasn't quite sure what to expect. All I knew was Google works fast! I hoped I could keep up.</span><span class="q" style="font-family:arial;"><br /><br />The first couple of weeks at Google required the most adjustment. While diving into my project's code and "Noogler" (new Googler) training courses, I came to the realization that this was going to be one of the most challenging experiences of my life. In the past, I've always associated challenging experiences with stress. But this was beginning to feel quite the opposite. Everyone around me was incredibly helpful, and the facilities were so comfortable that I actually found myself enjoying the challenge to the point of not wanting to leave work. The opportunity to learn at Google is literally endless, and I couldn't get enough.<br /><br />The great thing about test engineering is the ability to pick the challenges you want to attack. You get to find problems and attack code from angles that you never thought of before. The more you work and the more you test, the more you find out the RIGHT way of doing things, and just when you think you've got it perfect, you find a new way of optimizing your project's code. The product is as good as your testing proves it to be, and in a sense you become the gatekeeper for a product that is being used by millions worldwide. Having that responsibility is an amazing feeling. </span><span style="font-family:arial;"><br /><br />There were many projects available for me to work on at Google. From a test engineer's standpoint, there is always room for improvement in any product. I started my internship working on the back-end crawling and indexing components of Blog Search. After a few weeks of studying RSS technology and looking through Blog Search's parsing and indexing approach, the testing team and I were able to formulate a formal test plan that addressed potential security vulnerabilities and potential avenues for failure in many special case scenarios. Our code analysis and test cases will be constantly revisited and extended at every code change and will be the basis of many design decisions through the life of Blog Search. As my internship continued, I had the opportunity to work on several other projects, from small, new projects to larger, more established ones. I personally preferred the newer projects. I enjoy being involved from the beginning and being able to sit side-by-side with project managers and technical leads and give feedback about issues in the latest development. <br /><br />What's really fun is that every week, the entire NYC test engineering team gets together to sync up, share ideas, communicate issues, and share the latest news. This is where some of the great ideas get drawn up, and when something good hits the table, we pick it up and run with it! In my last few weeks at Google, we were able to draw a correlation between some common issues that we were all facing and identify the underlying challenges that needed to be addressed. Immediately, we started work on an automated testing framework that would solve most of our problems. When finished, it will be used not only by us, but possibly by every project team within Google.<br /><br />Overall, working at Google was a great experience. I had my share of fun, and I learned a great deal and am very grateful for the experience.</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:Abdul&#39;s Summer Intern Testimonial&url=https://testing.googleblog.com/2007/08/abduls-summer-intern-testimonial.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/2007/08/abduls-summer-intern-testimonial.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/08/abduls-summer-intern-testimonial.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/2007/08/abduls-summer-intern-testimonial.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/Patrick%20Copeland' rel='tag'> Patrick Copeland </a> </span> </div> </div> </div> <div class='post' data-id='453942152864529445' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/07/contributing-to-all-star-cast.html' itemprop='url' title='Contributing to an all-star CAST'> Contributing to an all-star CAST </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Thursday, July 26, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by Harry Robinson, Software Engineer in Test<br /><br />Lydia Ash and I, both Seattle Googlers, recently gave presentations at the second annual <a href="http://www.associationforsoftwaretesting.org/conference/index.html">Conference of the Association for Software Testing</a> (CAST) held in Bellevue, Washington, on July 9-11.<br /><br />CAST is an informative and challenging conference run entirely by volunteers from the testing community. We felt palpable enthusiasm for software testing throughout the event. In fact, if you had stopped by <a href="http://www.quardev.com/news/competition_and_exhibition_featured_at_seattle_area_software_testing_conference">Quardev</a> the evening before the conference, you would have seen a dozen testers from around the country preparing attendee packets, burning CDs, and having a great time arguing about boundary values.<br /><br />Lydia's presentation (<a href="http://www.associationforsoftwaretesting.org/conference/sessions.html#ash">Data Set Analysis: Approaches to Testing when the Build is the Data</a>) featured innovative heuristics used by the Google Maps team to detect subtle anomalies in large data sets.<br /><br />My talk on <a title="The Bionic Tester" href="http://www.associationforsoftwaretesting.org/conference/keynote.html#robinson">The Bionic Tester</a> showed how agile test automation can extend an exploratory tester's reach into complex features like Google Talk's Multi-User Chat.<br /><br />On the second evening, we sponsored the first-ever <a href="http://www.associationforsoftwaretesting.org/conference/sponsoredevents.html#test_exhibition">Tester Exhibition</a> in which several CAST presenters were asked to tell how they would use their expertise to test the CAST 2007 Registration page. The experts came at the problem from every direction and raised enough issues that the CAST organizers decided to <a title="disable the page" href="http://www.associationforsoftwaretesting.org/conference/registration.html">disable the page</a> prior to the Exhibition. :-)<p></p> <p>Slides and follow-up material from all CAST presentations are available through the <a title="CAST 2007 wiki" href="http://tejasconsulting.com/cast2007wiki/">CAST 2007 wiki</a>. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by Harry Robinson, Software Engineer in Test<br /><br />Lydia Ash and I, both Seattle Googlers, recently gave presentations at the second annual <a href="http://www.associationforsoftwaretesting.org/conference/index.html">Conference of the Association for Software Testing</a> (CAST) held in Bellevue, Washington, on July 9-11.<br /><br />CAST is an informative and challenging conference run entirely by volunteers from the testing community. We felt palpable enthusiasm for software testing throughout the event. In fact, if you had stopped by <a href="http://www.quardev.com/news/competition_and_exhibition_featured_at_seattle_area_software_testing_conference">Quardev</a> the evening before the conference, you would have seen a dozen testers from around the country preparing attendee packets, burning CDs, and having a great time arguing about boundary values.<br /><br />Lydia's presentation (<a href="http://www.associationforsoftwaretesting.org/conference/sessions.html#ash">Data Set Analysis: Approaches to Testing when the Build is the Data</a>) featured innovative heuristics used by the Google Maps team to detect subtle anomalies in large data sets.<br /><br />My talk on <a title="The Bionic Tester" href="http://www.associationforsoftwaretesting.org/conference/keynote.html#robinson">The Bionic Tester</a> showed how agile test automation can extend an exploratory tester's reach into complex features like Google Talk's Multi-User Chat.<br /><br />On the second evening, we sponsored the first-ever <a href="http://www.associationforsoftwaretesting.org/conference/sponsoredevents.html#test_exhibition">Tester Exhibition</a> in which several CAST presenters were asked to tell how they would use their expertise to test the CAST 2007 Registration page. The experts came at the problem from every direction and raised enough issues that the CAST organizers decided to <a title="disable the page" href="http://www.associationforsoftwaretesting.org/conference/registration.html">disable the page</a> prior to the Exhibition. :-)<p></p> <p>Slides and follow-up material from all CAST presentations are available through the <a title="CAST 2007 wiki" href="http://tejasconsulting.com/cast2007wiki/">CAST 2007 wiki</a>. <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:Contributing to an all-star CAST&url=https://testing.googleblog.com/2007/07/contributing-to-all-star-cast.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/2007/07/contributing-to-all-star-cast.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/07/contributing-to-all-star-cast.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/2007/07/contributing-to-all-star-cast.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/Harry%20Robinson' rel='tag'> Harry Robinson </a> </span> </div> </div> </div> <div class='post' data-id='8509845980973193776' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/07/google-new-york-test-engineering-forum.html' itemprop='url' title='Google New York Test Engineering Forum July 25'> Google New York Test Engineering Forum July 25 </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Friday, July 13, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by Zuri Kemp, Test Engineering Lead, Google New York<br /><br />Google New York is hosting a forum so that those of you in the local test engineering community can get to know one another while discussing topics significant to test engineers. This is a new series of events we're calling the Google New York Test Engineering Forum. So if you're a Test Engineer in the New York City tri-state area, please consider this your invitation to the kickoff forum on Wednesday, July 25th.<br /><br />For this first event, our panel will ask "Is there a career path in test engineering?" and "What is the value of a Test Engineer?". This is an informal session, and we welcome lots of audience participation.<br /><br />Register and learn more <a href="http://services.google.com/events/ny_eng_forum">here</a>. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by Zuri Kemp, Test Engineering Lead, Google New York<br /><br />Google New York is hosting a forum so that those of you in the local test engineering community can get to know one another while discussing topics significant to test engineers. This is a new series of events we're calling the Google New York Test Engineering Forum. So if you're a Test Engineer in the New York City tri-state area, please consider this your invitation to the kickoff forum on Wednesday, July 25th.<br /><br />For this first event, our panel will ask "Is there a career path in test engineering?" and "What is the value of a Test Engineer?". This is an informal session, and we welcome lots of audience participation.<br /><br />Register and learn more <a href="http://services.google.com/events/ny_eng_forum">here</a>. <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:Google New York Test Engineering Forum July 25&url=https://testing.googleblog.com/2007/07/google-new-york-test-engineering-forum.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/2007/07/google-new-york-test-engineering-forum.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/07/google-new-york-test-engineering-forum.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/2007/07/google-new-york-test-engineering-forum.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/Jobs' rel='tag'> Jobs </a> , <a class='label' href='https://testing.googleblog.com/search/label/Zuri%20Kemp' rel='tag'> Zuri Kemp </a> </span> </div> </div> </div> <div class='post' data-id='1069377068281266535' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/06/gtac-registration-closed.html' itemprop='url' title='GTAC registration closed'> GTAC registration closed </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Tuesday, June 19, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by Harry Robinson, Software Engineer in Test<br /><br />Thank you to everyone who applied to attend the Google Test Automation Conference in New York on August 23rd-24th. We received lots of applications for a very limited number of seats, so the choices were not easy.<br /><br />The sign-up website is now closed, and this week we'll be sending out acceptances and wait list notices. If you get an acceptance, congratulations -- we look forward to seeing you in New York. If you don't receive one, you'll be on the wait list, and we'll let you know if spaces become available. Either way, we'll let you know. If you don't hear from us in the next week, drop us <a title="a note" href="mailto:gtac-submission@google.com">a note</a>.<p>All the presentations from the conference will be posted on <a title="YouTube Google Channel" href="//www.youtube.com/user/google">YouTube Google Channel</a> within a New York minute after the speaker leaves the podium (well, maybe 72 New York minutes). We look forward to seeing you at the conference.</p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by Harry Robinson, Software Engineer in Test<br /><br />Thank you to everyone who applied to attend the Google Test Automation Conference in New York on August 23rd-24th. We received lots of applications for a very limited number of seats, so the choices were not easy.<br /><br />The sign-up website is now closed, and this week we'll be sending out acceptances and wait list notices. If you get an acceptance, congratulations -- we look forward to seeing you in New York. If you don't receive one, you'll be on the wait list, and we'll let you know if spaces become available. Either way, we'll let you know. If you don't hear from us in the next week, drop us <a title="a note" href="mailto:gtac-submission@google.com">a note</a>.<p>All the presentations from the conference will be posted on <a title="YouTube Google Channel" href="//www.youtube.com/user/google">YouTube Google Channel</a> within a New York minute after the speaker leaves the podium (well, maybe 72 New York minutes). We look forward to seeing you at the conference.</p> <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:GTAC registration closed&url=https://testing.googleblog.com/2007/06/gtac-registration-closed.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/2007/06/gtac-registration-closed.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/06/gtac-registration-closed.html#comments' style='font-weight: 500; text-decoration: underline;'>4 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/06/gtac-registration-closed.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='6382897261833502183' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/06/tott-extracting-methods-to-simplify.html' itemprop='url' title='TotT: Extracting Methods to Simplify Testing'> TotT: Extracting Methods to Simplify Testing </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Wednesday, June 13, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <p>When a method is long and complex, it is harder to test. You can make it easier by <b><span style="color:#800000;">extracting methods</span></b>: finding pieces of code in existing, complex methods (or functions) that can be replaced with method calls (or function calls). Consider the following complicated method:</p><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%; font-size:small"><pre><br /> def GetTestResults(self):<br /> <span style="color: rgb(0, 0, 255);"># Check if results have been cached.</span><br /> results = cache.get('test_results', None)<br /> if results is None:<br /> <span style="color: rgb(0, 0, 255);"># No results in the cache, so check the database.</span><br /> results = db.FetchResults(SQL_SELECT_TEST_RESULTS)<br /> <span style="color: rgb(0, 0, 255)"># Count passing and failing tests.</span><br /> num_passing = len([r for r in results if r['outcome'] == 'pass'])<br /> num_failing = len(results) - num_passing<br /> return num_passing, num_failing<br /></pre></blockquote><p>This method is difficult to test because it not only relies on a database, but also on a cache. In addition, it performs some post processing of the retrieved results. The first hint that this method could use refactoring is the abundance of comments. Extracting sections of code into well-named methods reduces the original method's complexity. When complexity is reduced, comments often become unnecessary. For example, consider the following:</p><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%; font-size:small;"><pre><br /> def GetTestResults(self):<br /> results = self._GetTestResultsFromCache()<br /> if results is None:<br /> results = self._GetTestResultsFromDatabase()<br /> return self._CountPassFail(results)<br /><br /> def _GetTestResultsFromCache(self):<br /> return cache.get('test_results', None)<br /><br /> def _GetTestResultsFromDatabase(self):<br /> return db.FetchResults(SQL_SELECT_TEST_RESULTS)<br /><br /> def _CountPassFail(self, results):<br /> num_passing = len([r for r in results if r['outcome'] == 'pass'])<br /> num_failing = len(results) - num_passing<br /> return num_passing, num_failing<br /><br /></pre></blockquote> <p>Now, tests can focus on each individual piece of the original method by testing each extracted method. This has the added benefit of making the code more readable and easier to maintain.</p><p>(Note: Method extraction can be done for you automatically in Python by the open-source refactoring browser BicycleRepairMan, and in Java by several IDEs, including IntelliJ IDEA and Eclipse.)</p><p>Remember to download <a href="http://code.google.com/testing/TotT-2007-06-13.pdf">this episode</a> of Testing on the Toilet and post it in your office.<br>&nbsp;</p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <p>When a method is long and complex, it is harder to test. You can make it easier by <b><span style="color:#800000;">extracting methods</span></b>: finding pieces of code in existing, complex methods (or functions) that can be replaced with method calls (or function calls). Consider the following complicated method:</p><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%; font-size:small"><pre><br /> def GetTestResults(self):<br /> <span style="color: rgb(0, 0, 255);"># Check if results have been cached.</span><br /> results = cache.get('test_results', None)<br /> if results is None:<br /> <span style="color: rgb(0, 0, 255);"># No results in the cache, so check the database.</span><br /> results = db.FetchResults(SQL_SELECT_TEST_RESULTS)<br /> <span style="color: rgb(0, 0, 255)"># Count passing and failing tests.</span><br /> num_passing = len([r for r in results if r['outcome'] == 'pass'])<br /> num_failing = len(results) - num_passing<br /> return num_passing, num_failing<br /></pre></blockquote><p>This method is difficult to test because it not only relies on a database, but also on a cache. In addition, it performs some post processing of the retrieved results. The first hint that this method could use refactoring is the abundance of comments. Extracting sections of code into well-named methods reduces the original method's complexity. When complexity is reduced, comments often become unnecessary. For example, consider the following:</p><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%; font-size:small;"><pre><br /> def GetTestResults(self):<br /> results = self._GetTestResultsFromCache()<br /> if results is None:<br /> results = self._GetTestResultsFromDatabase()<br /> return self._CountPassFail(results)<br /><br /> def _GetTestResultsFromCache(self):<br /> return cache.get('test_results', None)<br /><br /> def _GetTestResultsFromDatabase(self):<br /> return db.FetchResults(SQL_SELECT_TEST_RESULTS)<br /><br /> def _CountPassFail(self, results):<br /> num_passing = len([r for r in results if r['outcome'] == 'pass'])<br /> num_failing = len(results) - num_passing<br /> return num_passing, num_failing<br /><br /></pre></blockquote> <p>Now, tests can focus on each individual piece of the original method by testing each extracted method. This has the added benefit of making the code more readable and easier to maintain.</p><p>(Note: Method extraction can be done for you automatically in Python by the open-source refactoring browser BicycleRepairMan, and in Java by several IDEs, including IntelliJ IDEA and Eclipse.)</p><p>Remember to download <a href="http://code.google.com/testing/TotT-2007-06-13.pdf">this episode</a> of Testing on the Toilet and post it in your office.<br>&nbsp;</p> <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:TotT: Extracting Methods to Simplify Testing&url=https://testing.googleblog.com/2007/06/tott-extracting-methods-to-simplify.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/2007/06/tott-extracting-methods-to-simplify.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/06/tott-extracting-methods-to-simplify.html#comments' style='font-weight: 500; text-decoration: underline;'>2 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/06/tott-extracting-methods-to-simplify.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/TotT' rel='tag'> TotT </a> </span> </div> </div> </div> <div class='post' data-id='1959518006146064676' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/05/sign-up-to-attend-our-test-automation.html' itemprop='url' title='Sign up to attend our Test Automation Conference'> Sign up to attend our Test Automation Conference </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Wednesday, May 23, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <p>posted by Allen Hutchison, Engineering Manager<br /><br /> A few months ago we announced that we would be holding a <a href="http://googletesting.blogspot.com/2007/03/2nd-annual-google-test-automation.html" title="Google Test Automation Conference">Google Test Automation Conference</a> in New York City on August 23-24. Today, I'm happy to tell you that we've finalized the speaker list and have opened the <a href="http://services.google.com/events/gtac2007" title="registration process">attendee registration process</a>.<br /><br />The conference is completely free; however, because we have room for only 150 people, everyone who wishes to attend must apply and be accepted. You can apply to attend via <a href="http://services.google.com/events/gtac2007" title="this link">this link</a>, and we'll let you know by June 15 if your application has been accepted. </p> <p> </p> <p> At last year's conference, we found that the informal hallway discussions were tremendously valuable to everyone who came, and we would like to continue that custom. Therefore, the main point in the application process is to tell us how you can contribute to the conversation and what you would like to learn from the conference. </p> <p> </p> <p> To get you started, here is what our speakers will be talking about:<br /></p> <ul><li> Apple Chow and Santiago Etchebehere -- Building a flexible and extensible automation framework around Selenium </li><li> Ali-Akber Saifee -- muvee Framework for Autonomous Testing </li><li> Olivier Warin -- Spirent's WorkSuite Manager </li><li> Douglas Sellers -- CustomInk Domain Specific Language for automating an AJAX based application </li><li> Julian Harty -- Mobile Wireless Test Automation </li><li> Matt Heusser and Sean McMillan -- Examining Interaction-Based testing </li><li> Risto Kumpulainen -- Automated testing for F-Secure's Linux/UNIX Anti-Virus products </li><li> Sergio Pinon -- User Interface Functional Testing with AFTER (Automated Functional Testing Engine in Ruby) </li><li> Vivek Prahlad -- Functional Testing Swing applications with Frankenstein </li><li>Simon Stewart -- Web Driver </li><li> Adam Porter and Atif Memon -- Skoll distributed continuous quality assurance system </li><li> Cedric Beust -- TestNG </li><li> Hadar Ziv -- Specification-based Testing </li></ul> <p> </p> We look forward to your application and to a great conference. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <p>posted by Allen Hutchison, Engineering Manager<br /><br /> A few months ago we announced that we would be holding a <a href="http://googletesting.blogspot.com/2007/03/2nd-annual-google-test-automation.html" title="Google Test Automation Conference">Google Test Automation Conference</a> in New York City on August 23-24. Today, I'm happy to tell you that we've finalized the speaker list and have opened the <a href="http://services.google.com/events/gtac2007" title="registration process">attendee registration process</a>.<br /><br />The conference is completely free; however, because we have room for only 150 people, everyone who wishes to attend must apply and be accepted. You can apply to attend via <a href="http://services.google.com/events/gtac2007" title="this link">this link</a>, and we'll let you know by June 15 if your application has been accepted. </p> <p> </p> <p> At last year's conference, we found that the informal hallway discussions were tremendously valuable to everyone who came, and we would like to continue that custom. Therefore, the main point in the application process is to tell us how you can contribute to the conversation and what you would like to learn from the conference. </p> <p> </p> <p> To get you started, here is what our speakers will be talking about:<br /></p> <ul><li> Apple Chow and Santiago Etchebehere -- Building a flexible and extensible automation framework around Selenium </li><li> Ali-Akber Saifee -- muvee Framework for Autonomous Testing </li><li> Olivier Warin -- Spirent's WorkSuite Manager </li><li> Douglas Sellers -- CustomInk Domain Specific Language for automating an AJAX based application </li><li> Julian Harty -- Mobile Wireless Test Automation </li><li> Matt Heusser and Sean McMillan -- Examining Interaction-Based testing </li><li> Risto Kumpulainen -- Automated testing for F-Secure's Linux/UNIX Anti-Virus products </li><li> Sergio Pinon -- User Interface Functional Testing with AFTER (Automated Functional Testing Engine in Ruby) </li><li> Vivek Prahlad -- Functional Testing Swing applications with Frankenstein </li><li>Simon Stewart -- Web Driver </li><li> Adam Porter and Atif Memon -- Skoll distributed continuous quality assurance system </li><li> Cedric Beust -- TestNG </li><li> Hadar Ziv -- Specification-based Testing </li></ul> <p> </p> We look forward to your application and to a great conference. <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:Sign up to attend our Test Automation Conference&url=https://testing.googleblog.com/2007/05/sign-up-to-attend-our-test-automation.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/2007/05/sign-up-to-attend-our-test-automation.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/05/sign-up-to-attend-our-test-automation.html#comments' style='font-weight: 500; text-decoration: underline;'>14 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/05/sign-up-to-attend-our-test-automation.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='2383599154884582507' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/05/8-year-old-exploratory-testing.html' itemprop='url' title='8-year-old exploratory testing'> 8-year-old exploratory testing </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Wednesday, May 02, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by Allen Hutchison, Engineering Manager<br /><br />Earlier this week a colleague sent me a link to <a title="this post" href="http://www.cs.nyu.edu/%7Emichaels/blog/?p=15">this post</a> over on <a title="doodlebyte" href="http://www.cs.nyu.edu/%7Emichaels/blog/">doodlebyte</a>. In the post, Michael Schidlowsky talks about a recent experience watching an 8-year-old, play with Logo for the first time. The child was able to crash Logo in just a few commands. After that, Michael wanted to try to reproduce the bug:<br /><blockquote>I had played with UCBLogo for two weeks and hadn&#8217;t made it crash once. Brian brought the whole thing down in three commands. The most telling part is that when I tried to reproduce the defect a week later I couldn&#8217;t. I issued rt with a ton of 9s and just couldn&#8217;t get it to break. As it turns, it only crashes when you omit the space, which of course I didn&#8217;t think of doing. It took me more time to reproduce the defect than it took Brian to discover it.<br /></blockquote>This story vividly demonstrates two points about <a title="exploratory testing" href="http://en.wikipedia.org/wiki/Exploratory_test">exploratory testing</a>. First is that you have to be very careful to record everything you do during a testing session. In this case, Michael overlooked the fact that the 8-year-old had issued an "rt999..." instead of an "rt 999...". That made a huge difference to his testing and resulted in his taking a lot of time to reproduce the error. Some testers use screen recorders or key loggers to help with this issue.<br /><br />The other point is that we who use computers every day tend to adopt certain assumptions in our interaction with them. Michael didn't try "rt999..." because he knew that he should always put a space between a command and a parameter. When testing an application, we have to remember that our customers don't always hold the same assumptions that we do, whether they are 8 or 80 years old. Approach your testing with an awareness of your assumptions, and try to find out what happens when you break them. Often the results will surprise you. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by Allen Hutchison, Engineering Manager<br /><br />Earlier this week a colleague sent me a link to <a title="this post" href="http://www.cs.nyu.edu/%7Emichaels/blog/?p=15">this post</a> over on <a title="doodlebyte" href="http://www.cs.nyu.edu/%7Emichaels/blog/">doodlebyte</a>. In the post, Michael Schidlowsky talks about a recent experience watching an 8-year-old, play with Logo for the first time. The child was able to crash Logo in just a few commands. After that, Michael wanted to try to reproduce the bug:<br /><blockquote>I had played with UCBLogo for two weeks and hadn&#8217;t made it crash once. Brian brought the whole thing down in three commands. The most telling part is that when I tried to reproduce the defect a week later I couldn&#8217;t. I issued rt with a ton of 9s and just couldn&#8217;t get it to break. As it turns, it only crashes when you omit the space, which of course I didn&#8217;t think of doing. It took me more time to reproduce the defect than it took Brian to discover it.<br /></blockquote>This story vividly demonstrates two points about <a title="exploratory testing" href="http://en.wikipedia.org/wiki/Exploratory_test">exploratory testing</a>. First is that you have to be very careful to record everything you do during a testing session. In this case, Michael overlooked the fact that the 8-year-old had issued an "rt999..." instead of an "rt 999...". That made a huge difference to his testing and resulted in his taking a lot of time to reproduce the error. Some testers use screen recorders or key loggers to help with this issue.<br /><br />The other point is that we who use computers every day tend to adopt certain assumptions in our interaction with them. Michael didn't try "rt999..." because he knew that he should always put a space between a command and a parameter. When testing an application, we have to remember that our customers don't always hold the same assumptions that we do, whether they are 8 or 80 years old. Approach your testing with an awareness of your assumptions, and try to find out what happens when you break them. Often the results will surprise you. <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:8-year-old exploratory testing&url=https://testing.googleblog.com/2007/05/8-year-old-exploratory-testing.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/2007/05/8-year-old-exploratory-testing.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/05/8-year-old-exploratory-testing.html#comments' style='font-weight: 500; text-decoration: underline;'>5 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/05/8-year-old-exploratory-testing.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/Allen%20Hutchison' rel='tag'> Allen Hutchison </a> </span> </div> </div> </div> <div class='post' data-id='7199874977032232233' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/04/tott-refactoring-tests-in-red.html' itemprop='url' title='TotT: Refactoring Tests in the Red'> TotT: Refactoring Tests in the Red </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Thursday, April 26, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <p>With a good set of tests in place, refactoring code is much easier, as you can quickly gain a lot of confidence by running the tests again and making sure the code still passes.</p><p>As suites of tests grow, it's common to see duplication emerge. Like any code, tests should ideally be kept in a state that's easy to understand and maintain. So, you'll want to <strong><span style="color:#993300">refactor your tests</span></strong>, too.</p><p><strong><span style="color:#993300">However, refactoring tests can be hard because you don't have tests for the tests.</span></strong></p><p>How do you know that your refactoring of the tests was safe and you didn't accidentally remove one of the assertions?</p><p>If you <strong><span style="color:#993300">intentionally break the code under test</span></strong>, the failing test can show you that your assertions are still working. For example, if you were refactoring methods in <code>CombineHarvesterTest</code>, you would alter <code>CombineHarvester</code>, making it return the wrong results.</p><p>Check that the reason the tests are failing is because the assertions are failing as you'd expect them to. You can then (carefully) refactor the failing tests. If at any step they start passing, it immediately lets you know that the test is broken &#8211; undo! When you're done, remember to fix the code under test and make sure the tests pass again.<br>(<code>revert</code> is your friend, but <strong><span style="color:#993300">don't revert the tests</span></strong>!)</p><p>Let's repeat that important point:</p><p><strong><span style="color:#993300">When you're done...remember to fix the code under test!</span></strong></p><p><strong>Summary</strong></p><ul><li>Refactor <strong><span style="color:#993300">production</span></strong> code with the tests <strong><span style="color:#993300">passing</span></strong>. This helps you determine that the production code still does what it is meant to.</li><li>Refactor <strong><span style="color:#993300">test</span></strong> code with the tests <strong><span style="color:#993300">failing</span></strong>. This helps you determine that the test code still does what it is meant to.</li></ul><p>Remember to download <a href="http://code.google.com/testing/TotT-2007-04-25.pdf">this episode</a> of Testing on the Toilet and post it in your office.</p></p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <p>With a good set of tests in place, refactoring code is much easier, as you can quickly gain a lot of confidence by running the tests again and making sure the code still passes.</p><p>As suites of tests grow, it's common to see duplication emerge. Like any code, tests should ideally be kept in a state that's easy to understand and maintain. So, you'll want to <strong><span style="color:#993300">refactor your tests</span></strong>, too.</p><p><strong><span style="color:#993300">However, refactoring tests can be hard because you don't have tests for the tests.</span></strong></p><p>How do you know that your refactoring of the tests was safe and you didn't accidentally remove one of the assertions?</p><p>If you <strong><span style="color:#993300">intentionally break the code under test</span></strong>, the failing test can show you that your assertions are still working. For example, if you were refactoring methods in <code>CombineHarvesterTest</code>, you would alter <code>CombineHarvester</code>, making it return the wrong results.</p><p>Check that the reason the tests are failing is because the assertions are failing as you'd expect them to. You can then (carefully) refactor the failing tests. If at any step they start passing, it immediately lets you know that the test is broken &#8211; undo! When you're done, remember to fix the code under test and make sure the tests pass again.<br>(<code>revert</code> is your friend, but <strong><span style="color:#993300">don't revert the tests</span></strong>!)</p><p>Let's repeat that important point:</p><p><strong><span style="color:#993300">When you're done...remember to fix the code under test!</span></strong></p><p><strong>Summary</strong></p><ul><li>Refactor <strong><span style="color:#993300">production</span></strong> code with the tests <strong><span style="color:#993300">passing</span></strong>. This helps you determine that the production code still does what it is meant to.</li><li>Refactor <strong><span style="color:#993300">test</span></strong> code with the tests <strong><span style="color:#993300">failing</span></strong>. This helps you determine that the test code still does what it is meant to.</li></ul><p>Remember to download <a href="http://code.google.com/testing/TotT-2007-04-25.pdf">this episode</a> of Testing on the Toilet and post it in your office.</p></p> <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:TotT: Refactoring Tests in the Red&url=https://testing.googleblog.com/2007/04/tott-refactoring-tests-in-red.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/2007/04/tott-refactoring-tests-in-red.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/04/tott-refactoring-tests-in-red.html#comments' style='font-weight: 500; text-decoration: underline;'>5 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/04/tott-refactoring-tests-in-red.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/TotT' rel='tag'> TotT </a> </span> </div> </div> </div> <div class='post' data-id='1306987514498447314' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/04/test-engineering-in-zurich.html' itemprop='url' title='Test Engineering in Zurich'> Test Engineering in Zurich </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Wednesday, April 18, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by Phil Rollet, Senior Software QA Engineer<br /><p class="MsoNormal"><a title="Zurich, Switzerland" href="//maps.google.com/maps?f=q&amp;hl=en&amp;q=Freigutstrasse+12,+8002+Z%C3%BCrich,+Switzerland&amp;sll=37.0625,-95.677068&amp;sspn=97.532845,75.234375&amp;layer&amp;ie=UTF8&amp;z=16&amp;om=1&amp;iwloc=addr">Zurich, Switzerland</a> is the location of one of Google's largest engineering offices in Europe. We like to say it is no longer necessary to live in Silicon Valley to develop great software for Google, and the Zurich office has over 100 software engineers working on Google products and infrastructure. As a result the Zurich Test Engineering team is kept very busy. </p> <p class="MsoNormal">Producing great software is the driving motivation for each member of the Test Engineering team, which is relatively small by industry standards. But we're growing quickly and are passionate about software development, software quality, and testing. </p> <p class="MsoNormal">We work on several projects: some are customer-facing and some are infrastructure. We currently work on <a title="Google Maps" href="//www.google.com/maps">Google Maps</a>, which has testers and developers in several of our offices around the world. Our team builds tools to check the consistency of the data feeds that support the local search features in Maps. Another project mainly developed in Zurich is <a title="Google Transit" href="//www.google.com/transit">Google Transit</a>, which provides public transportation <span style="">itineraries</span> and schedule information for commuters who take trains, buses, and trams. On this project, we build tools to verify the proper alignment of the transportation layer of the map with the actual location coordinates of transit stops. We also focus on many projects related to Google&#8217;s infrastructure. For example, with <a title="Google Base API" href="http://code.google.com/apis/base">Google Base API</a>, we work with the Software Engineering team to measure response time and to track bottlenecks during large-scale bulk updates. </p> <p class="MsoNormal"><span style=""></span>Our aim is to assign local test engineers to most projects developed in this office, so <a title="hiring for this team is always a priority" href="http://www.google.ch/support/jobs/bin/topic.py?dep_id=1094&amp;loc_id=1115">hiring for this team is always a priority</a>. Candidates are from all over the world, and many different nationalities are represented in our office. Adapting to Zurich is quite easy, because it is already an international place: many companies have their headquarters here, and Zurich has been named the <a title="best city in the world for its quality of life" href="http://www.citymayors.com/features/quality_survey.html">best city in the world for its quality of life</a> in 2005, 2006, and 2007.</p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by Phil Rollet, Senior Software QA Engineer<br /><p class="MsoNormal"><a title="Zurich, Switzerland" href="//maps.google.com/maps?f=q&amp;hl=en&amp;q=Freigutstrasse+12,+8002+Z%C3%BCrich,+Switzerland&amp;sll=37.0625,-95.677068&amp;sspn=97.532845,75.234375&amp;layer&amp;ie=UTF8&amp;z=16&amp;om=1&amp;iwloc=addr">Zurich, Switzerland</a> is the location of one of Google's largest engineering offices in Europe. We like to say it is no longer necessary to live in Silicon Valley to develop great software for Google, and the Zurich office has over 100 software engineers working on Google products and infrastructure. As a result the Zurich Test Engineering team is kept very busy. </p> <p class="MsoNormal">Producing great software is the driving motivation for each member of the Test Engineering team, which is relatively small by industry standards. But we're growing quickly and are passionate about software development, software quality, and testing. </p> <p class="MsoNormal">We work on several projects: some are customer-facing and some are infrastructure. We currently work on <a title="Google Maps" href="//www.google.com/maps">Google Maps</a>, which has testers and developers in several of our offices around the world. Our team builds tools to check the consistency of the data feeds that support the local search features in Maps. Another project mainly developed in Zurich is <a title="Google Transit" href="//www.google.com/transit">Google Transit</a>, which provides public transportation <span style="">itineraries</span> and schedule information for commuters who take trains, buses, and trams. On this project, we build tools to verify the proper alignment of the transportation layer of the map with the actual location coordinates of transit stops. We also focus on many projects related to Google&#8217;s infrastructure. For example, with <a title="Google Base API" href="http://code.google.com/apis/base">Google Base API</a>, we work with the Software Engineering team to measure response time and to track bottlenecks during large-scale bulk updates. </p> <p class="MsoNormal"><span style=""></span>Our aim is to assign local test engineers to most projects developed in this office, so <a title="hiring for this team is always a priority" href="http://www.google.ch/support/jobs/bin/topic.py?dep_id=1094&amp;loc_id=1115">hiring for this team is always a priority</a>. Candidates are from all over the world, and many different nationalities are represented in our office. Adapting to Zurich is quite easy, because it is already an international place: many companies have their headquarters here, and Zurich has been named the <a title="best city in the world for its quality of life" href="http://www.citymayors.com/features/quality_survey.html">best city in the world for its quality of life</a> in 2005, 2006, and 2007.</p> <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:Test Engineering in Zurich&url=https://testing.googleblog.com/2007/04/test-engineering-in-zurich.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/2007/04/test-engineering-in-zurich.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/04/test-engineering-in-zurich.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/2007/04/test-engineering-in-zurich.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/Phil%20Rollet' rel='tag'> Phil Rollet </a> </span> </div> </div> </div> <div class='post' data-id='1974043656084761356' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/04/test-engineering-around-world.html' itemprop='url' title='Test Engineering around the world'> Test Engineering around the world </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Wednesday, April 18, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by Allen <span class="blsp-spelling-error" id="SPELLING_ERROR_0">Hutchison</span>, Engineering Manager<br /><br />The Test Engineering group at Google is truly a global organization. Our team is made up of test engineers in every corner of the world, working on all kinds of interesting projects. Today we are starting a series of blog posts to introduce you to our teams in different offices. Each post will give you some information on the testing projects we have in that particular office, and a little bit of the flavor of that region of the world. The global effort that makes up our test engineering team, and the diversity of ideas that are brought to bear on the challenges that we face, is one of our greatest strengths as a team.<br /><br />In the coming weeks and months, join me in learning more about Google Testing from a global perspective. Perhaps you'll find that we have a team in your part of the world. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by Allen <span class="blsp-spelling-error" id="SPELLING_ERROR_0">Hutchison</span>, Engineering Manager<br /><br />The Test Engineering group at Google is truly a global organization. Our team is made up of test engineers in every corner of the world, working on all kinds of interesting projects. Today we are starting a series of blog posts to introduce you to our teams in different offices. Each post will give you some information on the testing projects we have in that particular office, and a little bit of the flavor of that region of the world. The global effort that makes up our test engineering team, and the diversity of ideas that are brought to bear on the challenges that we face, is one of our greatest strengths as a team.<br /><br />In the coming weeks and months, join me in learning more about Google Testing from a global perspective. Perhaps you'll find that we have a team in your part of the world. <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:Test Engineering around the world&url=https://testing.googleblog.com/2007/04/test-engineering-around-world.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/2007/04/test-engineering-around-world.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/04/test-engineering-around-world.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/2007/04/test-engineering-around-world.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/Allen%20Hutchison' rel='tag'> Allen Hutchison </a> </span> </div> </div> </div> <div class='post' data-id='7923020007676146941' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/04/gtac-speaker-submission-window-closed.html' itemprop='url' title='GTAC Speaker Submission Window Closed'> GTAC Speaker Submission Window Closed </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Tuesday, April 17, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by <span id="mgSecretSpan_0" class="mgSecretSpan">Allen Hutchison,</span> Engineering Manager<br /><br />Thank you to everyone who submitted a proposal to speak at the <a title="Google Test Automation Conference" href="http://googletesting.blogspot.com/2007/03/2nd-annual-google-test-automation.html">Google Test Automation Conference</a>. We'll be reading each proposal closely and selecting those that we think are best for the conference. If you submitted a proposal, <span id="mgSecretSpan_1" class="mgSecretSpan">then</span> we'll be getting in touch with you directly to let you know if it was accepted or not.<br /><br />If you didn't submit a proposal, but are interested in attending, <span id="mgSecretSpan_2" class="mgSecretSpan">then</span> check back on the <a title="Google Testing Blog" href="http://googletesting.blogspot.com/">Google Testing Blog</a> on May 7 to see the conference schedule and instructions for how to apply to attend. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by <span id="mgSecretSpan_0" class="mgSecretSpan">Allen Hutchison,</span> Engineering Manager<br /><br />Thank you to everyone who submitted a proposal to speak at the <a title="Google Test Automation Conference" href="http://googletesting.blogspot.com/2007/03/2nd-annual-google-test-automation.html">Google Test Automation Conference</a>. We'll be reading each proposal closely and selecting those that we think are best for the conference. If you submitted a proposal, <span id="mgSecretSpan_1" class="mgSecretSpan">then</span> we'll be getting in touch with you directly to let you know if it was accepted or not.<br /><br />If you didn't submit a proposal, but are interested in attending, <span id="mgSecretSpan_2" class="mgSecretSpan">then</span> check back on the <a title="Google Testing Blog" href="http://googletesting.blogspot.com/">Google Testing Blog</a> on May 7 to see the conference schedule and instructions for how to apply to attend. <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:GTAC Speaker Submission Window Closed&url=https://testing.googleblog.com/2007/04/gtac-speaker-submission-window-closed.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/2007/04/gtac-speaker-submission-window-closed.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/04/gtac-speaker-submission-window-closed.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/2007/04/gtac-speaker-submission-window-closed.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='4695027454724990070' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/04/test-engineering-internships.html' itemprop='url' title='Test Engineering Internships'> Test Engineering Internships </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Monday, April 16, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by Zuri Kemp, Lead Software Quality Assurance Engineer<br /><br />Thinking about becoming a Google test engineering intern? Want to help us organize the world's information and make it universally accessible and useful -- but you're not sure what it's really like here? Over the next several months we'll be featuring articles by former Test Engineering interns. Until then, here's a top-10 list of adjectives to describe software engineers at Google:<br /><ul><li>Global - Google has engineering offices (and, of course, customers) all over the world. So not only do we have engineers from everywhere, every engineer gets the chance to make software that will be as great in Singapore as it is in Finland.</li><li>Comfortable - Engineers need to be comfortable to be effective...and Google gives us the equipment to be comfortable. And if our muscles get tight from sitting, we can get an on-site professional massage.</li><li>Flexible - Getting work done is more important than what time we work.</li><li>Unhampered - We're a company designed by engineers for engineers, so functional merit tends to outweigh other considerations at decision-making time.</li><li>Entertained - We have lots of fun activities. Every winter, there's a company-wide ski trip. Every summer, there's an all-engineer picnic on the Santa Cruz beach boardwalk. Google has bought out theaters for opening days of films like Star Wars and Lord of the Rings.</li><li>Listened to - Google has a very open environment and truly values each employee's opinions. Every Friday, there's a company-wide meeting where Larry and Sergey (our founders) report on significant events and have an open-to-all Q&A session.</li><li>Stuffed - In most offices, Google provides free gourmet-quality breakfast, lunch, and dinner. If you come in too late to get breakfast (or you get hungry between meals), you can always head to the nearby mini-kitchen and grab some fruit, cereal, and tea (or crisps, chocolate, and espresso for the less healthily inclined).</li><li> Cutting-edge - We have the audacious goal of organizing the world's information -- and to meet it, we've built the largest distributed computer system in the world and written some of the world's most widely-used software.</li><li> High-impact - People in every country and every language use our products.</li><li> Dependable - We try to keep a high bar for hiring, so you can depend on the ability of your teammates to handle most any engineering problem.</li></ul>If all of that (<a href="//www.google.com/support/jobs/bin/static.py?page=about.html&amp;about=eng2">and this</a>) wasn't enough to convince you that Google is a fantastic environment for a software engineer in test, consider being able to "make and break" cool Google products. That is exactly what test engineers at Google do. We not only manually find flaws in software engineers' code, we also build smart, home-grown tools that effectively break and test the limits of web software.<br /><br />While the deadline for Test Engineering internships for this summer is past, we want to help you make a decision for your internship next year. Stay tuned to our blog, we'll be posting a regular series on Test Engineering internships at Google. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by Zuri Kemp, Lead Software Quality Assurance Engineer<br /><br />Thinking about becoming a Google test engineering intern? Want to help us organize the world's information and make it universally accessible and useful -- but you're not sure what it's really like here? Over the next several months we'll be featuring articles by former Test Engineering interns. Until then, here's a top-10 list of adjectives to describe software engineers at Google:<br /><ul><li>Global - Google has engineering offices (and, of course, customers) all over the world. So not only do we have engineers from everywhere, every engineer gets the chance to make software that will be as great in Singapore as it is in Finland.</li><li>Comfortable - Engineers need to be comfortable to be effective...and Google gives us the equipment to be comfortable. And if our muscles get tight from sitting, we can get an on-site professional massage.</li><li>Flexible - Getting work done is more important than what time we work.</li><li>Unhampered - We're a company designed by engineers for engineers, so functional merit tends to outweigh other considerations at decision-making time.</li><li>Entertained - We have lots of fun activities. Every winter, there's a company-wide ski trip. Every summer, there's an all-engineer picnic on the Santa Cruz beach boardwalk. Google has bought out theaters for opening days of films like Star Wars and Lord of the Rings.</li><li>Listened to - Google has a very open environment and truly values each employee's opinions. Every Friday, there's a company-wide meeting where Larry and Sergey (our founders) report on significant events and have an open-to-all Q&A session.</li><li>Stuffed - In most offices, Google provides free gourmet-quality breakfast, lunch, and dinner. If you come in too late to get breakfast (or you get hungry between meals), you can always head to the nearby mini-kitchen and grab some fruit, cereal, and tea (or crisps, chocolate, and espresso for the less healthily inclined).</li><li> Cutting-edge - We have the audacious goal of organizing the world's information -- and to meet it, we've built the largest distributed computer system in the world and written some of the world's most widely-used software.</li><li> High-impact - People in every country and every language use our products.</li><li> Dependable - We try to keep a high bar for hiring, so you can depend on the ability of your teammates to handle most any engineering problem.</li></ul>If all of that (<a href="//www.google.com/support/jobs/bin/static.py?page=about.html&amp;about=eng2">and this</a>) wasn't enough to convince you that Google is a fantastic environment for a software engineer in test, consider being able to "make and break" cool Google products. That is exactly what test engineers at Google do. We not only manually find flaws in software engineers' code, we also build smart, home-grown tools that effectively break and test the limits of web software.<br /><br />While the deadline for Test Engineering internships for this summer is past, we want to help you make a decision for your internship next year. Stay tuned to our blog, we'll be posting a regular series on Test Engineering internships at Google. <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:Test Engineering Internships&url=https://testing.googleblog.com/2007/04/test-engineering-internships.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/2007/04/test-engineering-internships.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/04/test-engineering-internships.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/2007/04/test-engineering-internships.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/Zuri%20Kemp' rel='tag'> Zuri Kemp </a> </span> </div> </div> </div> <div class='post' data-id='5947176721635235314' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/04/tott-stubs-speed-up-your-unit-tests.html' itemprop='url' title='TotT: Stubs Speed up Your Unit Tests'> TotT: Stubs Speed up Your Unit Tests </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Wednesday, April 04, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> <p>Michael Feathers defines the qualities of a good unit test as: &#8220;they run fast, they help us localize problems.&#8221; This can be hard to accomplish when your code accesses a database, hits another server, is time-dependent, etc.</p><p>By substituting custom objects for some of your module's dependencies, you can thoroughly test your code, increase your coverage, and still run in less than a second. You can even simulate rare scenarios like database failures and test your error handling code.</p><p>A variety of different terms are used to refer to these &#8220;custom objects&#8221;. In an effort to clarify the vocabulary, Gerard Meszaros provides the following definitions:</p><ul><li><strong>Test Double</strong> is a generic term for any test object that replaces a production object.</li><li><strong>Dummy</strong> objects are passed around but not actually used. They are usually fillers for parameter lists.</li><li><strong>Fakes</strong> have working implementations, but take some shortcut (e.g., InMemoryDatabase).</li><li><strong>Stubs</strong> provide canned answers to calls made during a test.</li><li><strong>Mocks</strong> have expectations which form a specification of the calls they do and do not receive.</li></ul><p>For example, to test a simple method like getIdPrefix() in the IdGetter class:</p><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%;"><pre><br /><strong>public class <span style="color:#993300">IdGetter</span></strong> { <span style="color:#0000FF">// Constructor omitted.</span><br /> <strong>public</strong> String <span style="font-weight:bold; color:#993300">getIdPrefix</span>() {<br /> <strong>try</strong> {<br /> String s = db.selectString("select id from foo");<br /> <strong>return</strong> s.substring(0, 5);<br /> } <strong>catch</strong> (SQLException e) { <strong>return</strong> ""; }<br /> }<br />}</pre></blockquote><p>You could write:</p><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%;"><pre><br /> db.execute("create table foo (id varchar(40))"); <span style="color:#0000FF">// db created in setUp().</span><br /> db.execute("insert into foo (id) values ('hello world!')");<br /> IdGetter getter = <strong>new</strong> IdGetter(db);<br /> assertEquals("hello", getter.getIdPrefix());</pre></blockquote><p>The test above works but takes a relatively long time to run (network access), can be unreliable (db machine might be down), and makes it hard to test for errors. You can <strong>avoid these pitfalls by using stubs:</strong></p><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%;"><pre><br /> <strong>public class <span style="color:#993300">StubDbThatReturnsId</span> extends</strong> Database {<br /> <strong>public</strong> String selectString(String query) { <strong>return</strong> "hello world"; }<br /> }<br /> <strong>public class <span style="color:#993300">StubDbThatFails</span> extends</strong> Database {<br /> <strong>public</strong> String selectString(String query) <strong>throws</strong> SQLException {<br /> <strong>throw new</strong> SQLException("Fake DB failure");<br /> }<br /> }<br /> <strong>public void</strong> testReturnsFirstFiveCharsOfId() <strong>throws</strong> Exception {<br /> IdGetter getter = <strong>new</strong> IdGetter(<strong>new <span style="color:#993300">StubDbThatReturnsId</span></strong>());<br /> assertEquals("hello", getter.getIdPrefix());<br /> }<br /> <strong>public void</strong> testReturnsEmptyStringIfIdNotFound() <strong>throws</strong> Exception {<br /> IdGetter getter = <strong>new</strong> IdGetter(<strong>new <span style="color:#993300">StubDbThatFails</span></strong>());<br /> assertEquals("", getter.getIdPrefix());<br /> }</pre></blockquote><p>Remember to download <a href="http://code.google.com/testing/TotT-2007-04-04.pdf">this episode</a> of Testing on the Toilet and post it in your office.<br />&nbsp;</p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> <p>Michael Feathers defines the qualities of a good unit test as: &#8220;they run fast, they help us localize problems.&#8221; This can be hard to accomplish when your code accesses a database, hits another server, is time-dependent, etc.</p><p>By substituting custom objects for some of your module's dependencies, you can thoroughly test your code, increase your coverage, and still run in less than a second. You can even simulate rare scenarios like database failures and test your error handling code.</p><p>A variety of different terms are used to refer to these &#8220;custom objects&#8221;. In an effort to clarify the vocabulary, Gerard Meszaros provides the following definitions:</p><ul><li><strong>Test Double</strong> is a generic term for any test object that replaces a production object.</li><li><strong>Dummy</strong> objects are passed around but not actually used. They are usually fillers for parameter lists.</li><li><strong>Fakes</strong> have working implementations, but take some shortcut (e.g., InMemoryDatabase).</li><li><strong>Stubs</strong> provide canned answers to calls made during a test.</li><li><strong>Mocks</strong> have expectations which form a specification of the calls they do and do not receive.</li></ul><p>For example, to test a simple method like getIdPrefix() in the IdGetter class:</p><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%;"><pre><br /><strong>public class <span style="color:#993300">IdGetter</span></strong> { <span style="color:#0000FF">// Constructor omitted.</span><br /> <strong>public</strong> String <span style="font-weight:bold; color:#993300">getIdPrefix</span>() {<br /> <strong>try</strong> {<br /> String s = db.selectString("select id from foo");<br /> <strong>return</strong> s.substring(0, 5);<br /> } <strong>catch</strong> (SQLException e) { <strong>return</strong> ""; }<br /> }<br />}</pre></blockquote><p>You could write:</p><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%;"><pre><br /> db.execute("create table foo (id varchar(40))"); <span style="color:#0000FF">// db created in setUp().</span><br /> db.execute("insert into foo (id) values ('hello world!')");<br /> IdGetter getter = <strong>new</strong> IdGetter(db);<br /> assertEquals("hello", getter.getIdPrefix());</pre></blockquote><p>The test above works but takes a relatively long time to run (network access), can be unreliable (db machine might be down), and makes it hard to test for errors. You can <strong>avoid these pitfalls by using stubs:</strong></p><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%;"><pre><br /> <strong>public class <span style="color:#993300">StubDbThatReturnsId</span> extends</strong> Database {<br /> <strong>public</strong> String selectString(String query) { <strong>return</strong> "hello world"; }<br /> }<br /> <strong>public class <span style="color:#993300">StubDbThatFails</span> extends</strong> Database {<br /> <strong>public</strong> String selectString(String query) <strong>throws</strong> SQLException {<br /> <strong>throw new</strong> SQLException("Fake DB failure");<br /> }<br /> }<br /> <strong>public void</strong> testReturnsFirstFiveCharsOfId() <strong>throws</strong> Exception {<br /> IdGetter getter = <strong>new</strong> IdGetter(<strong>new <span style="color:#993300">StubDbThatReturnsId</span></strong>());<br /> assertEquals("hello", getter.getIdPrefix());<br /> }<br /> <strong>public void</strong> testReturnsEmptyStringIfIdNotFound() <strong>throws</strong> Exception {<br /> IdGetter getter = <strong>new</strong> IdGetter(<strong>new <span style="color:#993300">StubDbThatFails</span></strong>());<br /> assertEquals("", getter.getIdPrefix());<br /> }</pre></blockquote><p>Remember to download <a href="http://code.google.com/testing/TotT-2007-04-04.pdf">this episode</a> of Testing on the Toilet and post it in your office.<br />&nbsp;</p> <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:TotT: Stubs Speed up Your Unit Tests&url=https://testing.googleblog.com/2007/04/tott-stubs-speed-up-your-unit-tests.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/2007/04/tott-stubs-speed-up-your-unit-tests.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/04/tott-stubs-speed-up-your-unit-tests.html#comments' style='font-weight: 500; text-decoration: underline;'>5 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/04/tott-stubs-speed-up-your-unit-tests.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/TotT' rel='tag'> TotT </a> </span> </div> </div> </div> <div class='post' data-id='8929130970843213113' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/04/google-test-automation-conference.html' itemprop='url' title='Google Test Automation Conference submission deadline coming soon'> Google Test Automation Conference submission deadline coming soon </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Tuesday, April 03, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by <span class="mgSecretSpan"><span id="mgSecretSpan_0" class="mgSecretSpan">Allen Hutchison,</span></span> Engineering Manager<br /><br />If you recall, <a href="http://googletesting.blogspot.com/2007/03/2nd-annual-google-test-automation.html" title="we announced the Google Test Automation Conference here">we announced the Google Test Automation Conference here</a> about a month ago. To everyone who has submitted a proposal to speak at the conference, thank you. To those of you who haven't yet submitted your proposal, I want to remind you that the deadline for submissions is this Friday, April 6.<br /><br />We're looking for speakers with exciting ideas and new approaches to test automation. If you have a subject you'd like to talk about, please send an email to <a href="mailto:gtac-submission@google.com/" title="gtac-submission@google.com">gtac-submission@google.com</a> and include a description of your 45 minute session in 500 words or less (no attachments, please). Deadline for submissions is <span style="font-weight: bold;">April 6</span>. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by <span class="mgSecretSpan"><span id="mgSecretSpan_0" class="mgSecretSpan">Allen Hutchison,</span></span> Engineering Manager<br /><br />If you recall, <a href="http://googletesting.blogspot.com/2007/03/2nd-annual-google-test-automation.html" title="we announced the Google Test Automation Conference here">we announced the Google Test Automation Conference here</a> about a month ago. To everyone who has submitted a proposal to speak at the conference, thank you. To those of you who haven't yet submitted your proposal, I want to remind you that the deadline for submissions is this Friday, April 6.<br /><br />We're looking for speakers with exciting ideas and new approaches to test automation. If you have a subject you'd like to talk about, please send an email to <a href="mailto:gtac-submission@google.com/" title="gtac-submission@google.com">gtac-submission@google.com</a> and include a description of your 45 minute session in 500 words or less (no attachments, please). Deadline for submissions is <span style="font-weight: bold;">April 6</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:Google Test Automation Conference submission deadline coming soon&url=https://testing.googleblog.com/2007/04/google-test-automation-conference.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/2007/04/google-test-automation-conference.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/04/google-test-automation-conference.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/2007/04/google-test-automation-conference.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='4731914586629232935' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/03/javascript-simulating-time-in-jsunit.html' itemprop='url' title='TotT: JavaScript: Simulating Time in jsUnit Tests'> TotT: JavaScript: Simulating Time in jsUnit Tests </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Thursday, March 29, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Sometimes you need to test client-side JavaScript code that uses <code>setTimeout()</code> to do some work in the future. <code>jsUnit</code> contains the <code>Clock.tick()</code> method, which simulates time passing without causing the test to sleep. For example, this function will set up some callbacks to update a status message over the course of four seconds:<br /><br /><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin:-moz-initial; -moz-background-inline-policy: -moz-initial;"><pre><br />function showProgress(status) {<br /> status.message = "Loading";<br /> for (var time = 1000; time <= 3000; time += 1000) {<br /> <em>// Append a '.' to the message every second for 3 secs.</em><br /> setTimeout(function() {<br /> status.message += ".";<br /> }, time);<br /> }<br /> setTimeout(function() {<br /> <em>// Special case for the 4th second.</em><br /> status.message = "Done";<br /> }, 4000);<br />}<br /></pre></blockquote><br /><br />The jsUnit test for this function would look like this:<br /><br /><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin:-moz-initial; -moz-background-inline-policy: -moz-initial;"><pre><br />function testUpdatesStatusMessageOverFourSeconds() {<br /> Clock.reset(); <em>// Clear any existing timeout functions on the event queue.</em><br /> var status = {};<br /> showProgress(status); <em>// Call our function.</em><br /> assertEquals("Loading", status.message);<br /> Clock.tick(2000); <em>// Call any functions on the event queue that have</em><br /> <em>// been scheduled for the first two seconds.</em><br /> assertEquals("Loading..", status.message);<br /> Clock.tick(2000); <em>// Same thing again, for the next two seconds.</em><br /> assertEquals("Done", status.message);<br />}<br /></pre></blockquote><br /><br />This test will run very quickly - it does not require four seconds to run.<br /><br /><code>Clock</code> supports the functions <code>setTimeout()</code>,<br /><code>setInterval()</code>, <code>clearTimeout()</code>, and<br /><code>clearInterval()</code>. The Clock object is defined in<br /><code>jsUnitMockTimeout.js</code>, which is in the same directory as<br /><code>jsUnitCore.js</code>.<br /><br />Remember to <a href="http://code.google.com/testing/TotT-2007-03-29.pdf">download this episode</a> of Testing on the Toilet and post it in your office. <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Sometimes you need to test client-side JavaScript code that uses <code>setTimeout()</code> to do some work in the future. <code>jsUnit</code> contains the <code>Clock.tick()</code> method, which simulates time passing without causing the test to sleep. For example, this function will set up some callbacks to update a status message over the course of four seconds:<br /><br /><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin:-moz-initial; -moz-background-inline-policy: -moz-initial;"><pre><br />function showProgress(status) {<br /> status.message = "Loading";<br /> for (var time = 1000; time <= 3000; time += 1000) {<br /> <em>// Append a '.' to the message every second for 3 secs.</em><br /> setTimeout(function() {<br /> status.message += ".";<br /> }, time);<br /> }<br /> setTimeout(function() {<br /> <em>// Special case for the 4th second.</em><br /> status.message = "Done";<br /> }, 4000);<br />}<br /></pre></blockquote><br /><br />The jsUnit test for this function would look like this:<br /><br /><blockquote style="background: rgb(255, 255, 224) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin:-moz-initial; -moz-background-inline-policy: -moz-initial;"><pre><br />function testUpdatesStatusMessageOverFourSeconds() {<br /> Clock.reset(); <em>// Clear any existing timeout functions on the event queue.</em><br /> var status = {};<br /> showProgress(status); <em>// Call our function.</em><br /> assertEquals("Loading", status.message);<br /> Clock.tick(2000); <em>// Call any functions on the event queue that have</em><br /> <em>// been scheduled for the first two seconds.</em><br /> assertEquals("Loading..", status.message);<br /> Clock.tick(2000); <em>// Same thing again, for the next two seconds.</em><br /> assertEquals("Done", status.message);<br />}<br /></pre></blockquote><br /><br />This test will run very quickly - it does not require four seconds to run.<br /><br /><code>Clock</code> supports the functions <code>setTimeout()</code>,<br /><code>setInterval()</code>, <code>clearTimeout()</code>, and<br /><code>clearInterval()</code>. The Clock object is defined in<br /><code>jsUnitMockTimeout.js</code>, which is in the same directory as<br /><code>jsUnitCore.js</code>.<br /><br />Remember to <a href="http://code.google.com/testing/TotT-2007-03-29.pdf">download this episode</a> of Testing on the Toilet and post it in your office. <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:TotT: JavaScript: Simulating Time in jsUnit Tests&url=https://testing.googleblog.com/2007/03/javascript-simulating-time-in-jsunit.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/2007/03/javascript-simulating-time-in-jsunit.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/03/javascript-simulating-time-in-jsunit.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/2007/03/javascript-simulating-time-in-jsunit.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/JavaScript' rel='tag'> JavaScript </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='5601414323604654672' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/03/robot-testers-invade-portland_15.html' itemprop='url' title='Robot testers invade Portland'> Robot testers invade Portland </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Thursday, March 15, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by <span class="mgSecretSpan"><span class="mgSecretSpan"><span id="mgSecretSpan_0" class="mgSecretSpan">Harry Robinson,</span></span></span> Software Engineer in Test<br /><br /><p><span class="Text"><span class="Text"><span class="Text"><span class="Text">Software testing is tough. It can be exhausting, and there is rarely enough time to find all the important bugs. Wouldn't it be nice to have a staff of tireless servants working day and night to make you look good? <span class="Text">Well, those days are here.</span></span></span></span></span> On Thursday, March 22, <span class="mgSecretSpan"><span class="mgSecretSpan"></span></span>I'll give a lunchtime presentation titled "<strong><a title="How to Build Your Own Robot Army" href="http://db.sao.org/calendar2/event_description.htm?eventID=3/22/07">How to Build Your Own Robot Army</a></strong>" for the Quality Assurance SIG of the <a title="Software Association of Oregon" href="http://www.sao.org/">Software Association of Oregon</a>. </p> <p><span class="Text"><span class="Text"><span class="Text"></span></span></span></p> <p><span class="Text"><span class="Text"><span class="Text"></span></span><br /></span></p> <p><span class="Text">Two decades ago, machine time was expensive, so test suites had to run as quickly and efficiently as possible. Today, CPUs are cheap, so it becomes reasonable to move test creation to the shoulders of a test machine army. But we're not talking about the run-of-the-mill automated scripts that only do what you explicitly told them. We're talking about programs that create and execute tests you never thought of to find bugs you never dreamed of. From Orcs to Zergs to Droids to Cyborgs, this presentation will show how to create a robot test army using tools lying around on the Web. Most importantly, it will cover how to take appropriate credit for your army's work!</span> </p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by <span class="mgSecretSpan"><span class="mgSecretSpan"><span id="mgSecretSpan_0" class="mgSecretSpan">Harry Robinson,</span></span></span> Software Engineer in Test<br /><br /><p><span class="Text"><span class="Text"><span class="Text"><span class="Text">Software testing is tough. It can be exhausting, and there is rarely enough time to find all the important bugs. Wouldn't it be nice to have a staff of tireless servants working day and night to make you look good? <span class="Text">Well, those days are here.</span></span></span></span></span> On Thursday, March 22, <span class="mgSecretSpan"><span class="mgSecretSpan"></span></span>I'll give a lunchtime presentation titled "<strong><a title="How to Build Your Own Robot Army" href="http://db.sao.org/calendar2/event_description.htm?eventID=3/22/07">How to Build Your Own Robot Army</a></strong>" for the Quality Assurance SIG of the <a title="Software Association of Oregon" href="http://www.sao.org/">Software Association of Oregon</a>. </p> <p><span class="Text"><span class="Text"><span class="Text"></span></span></span></p> <p><span class="Text"><span class="Text"><span class="Text"></span></span><br /></span></p> <p><span class="Text">Two decades ago, machine time was expensive, so test suites had to run as quickly and efficiently as possible. Today, CPUs are cheap, so it becomes reasonable to move test creation to the shoulders of a test machine army. But we're not talking about the run-of-the-mill automated scripts that only do what you explicitly told them. We're talking about programs that create and execute tests you never thought of to find bugs you never dreamed of. From Orcs to Zergs to Droids to Cyborgs, this presentation will show how to create a robot test army using tools lying around on the Web. Most importantly, it will cover how to take appropriate credit for your army's work!</span> </p> <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:Robot testers invade Portland&url=https://testing.googleblog.com/2007/03/robot-testers-invade-portland_15.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/2007/03/robot-testers-invade-portland_15.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/03/robot-testers-invade-portland_15.html#comments' style='font-weight: 500; text-decoration: underline;'>8 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/03/robot-testers-invade-portland_15.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/Harry%20Robinson' rel='tag'> Harry Robinson </a> </span> </div> </div> </div> <div class='post' data-id='6169943990631187059' itemscope='' itemtype='http://schema.org/BlogPosting'> <h2 class='title' itemprop='name'> <a href='https://testing.googleblog.com/2007/03/developer-testertester-developer-summit.html' itemprop='url' title='Developer-Tester/Tester-Developer Summit'> Developer-Tester/Tester-Developer Summit </a> </h2> <div class='post-header'> <div class='published'> <span class='publishdate' itemprop='datePublished'> Monday, March 12, 2007 </span> </div> </div> <div class='post-body'> <div class='post-content' itemprop='articleBody'> <script type='text/template'> Posted by <span class="mgSecretSpan"><span id="mgSecretSpan_0" class="mgSecretSpan">Harry Robinson,</span></span> Software Engineer in Test <div style="color: rgb(0, 0, 0);"> <p> <span style="font-family:Arial;font-size:100%;">The first-ever industry </span><a href="http://chrismcmahonsblog.blogspot.com/2007/01/announcing-bay-area-developer.html" title="Announcing the Bay Area Developer-Tester/Tester-Developer Summit "><span style="font-family:Arial;font-size:100%;">Developer-Tester/Tester<wbr>-Developer Summit</span></a><span style="font-family:Arial;font-size:100%;"> was held at the Mountain View Googleplex on Saturday, February 24th. Hosted by </span><a href="http://www.testobsessed.com/" target="_blank" title="Elisabeth Hendrickson"><span style="font-family:Arial;font-size:100%;">Elisabeth Hendrickson</span></a><span style="font-family:Arial;font-size:100%;"> and </span><a href="http://chrismcmahonsblog.blogspot.com/" target="_blank" title="Chris McMahon"><span style="font-family:Arial;font-size:100%;">Chris McMahon</span></a><span style="font-family:Arial;font-size:100%;">, the all-day workshop consisted of experience reports and lightning talks including:</span> </p> </div> <div style="color: rgb(0, 0, 0);"> </div> <ul style="color: rgb(0, 0, 0);"><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Al Snow - Form Letter Generator Technique </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Chris McMahon &#8211; Emulating User Actions in Random and Deterministic Modes </span></span> </p> </li><li> <p> <span style="font-family:Arial;font-size:100%;">Dave Liebreich &#8211; Test Mozilla </span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">David Martinez &#8211; Tk-Acceptance </span></span> </p> </li><li> <p> <span style="font-family:Arial;font-size:100%;">Dave W. Smith &#8211; System Effects of Slow Tests</span> </p> </li><li> <p> <span style="font-family:Arial;font-size:100%;"><span class="mgSecretSpan"><span class="mgSecretSpan"><span id="mgSecretSpan_1" class="mgSecretSpan">Harry Robinson</span></span></span> &#8211; <a href="http://model.based.testing.googlepages.com/exploratory-automation.pdf" title="Exploratory Automation">Exploratory Automation</a> </span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Jason Reid &#8211; Not Trusting Your Developers </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Jeff Brown &#8211; MBUnit </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Jeff Fry &#8211; <a href="http://testingjeff.wordpress.com/2007/01/27/creating-methods-on-the-flyand-bugs-in-google-phonebook/" title="Generating Methods on the Fly">Generating Methods on the Fly</a> </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Keith Ray &#8211; ckr_spec </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Kurman Karabukaev &#8211; Whitebox testing using Watir </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;"><span class="mgSecretSpan"><span class="mgSecretSpan">Mark Striebeck</span></span> &#8211; How to Get Developers and Tester to Work Closer Together </span></span> </p> </li><li> <p> <span style="font-family:Arial;font-size:100%;">Sergio Pinon &#8211; UI testing + Cruise Control </span> </p> </li></ul> <ul style="color: rgb(0, 0, 0);"><div> </div></ul> <div style="color: rgb(0, 0, 0);"> <p> <span style="font-family:Arial;font-size:100%;">There were also brainstorming exercises and discussions on the benefits that DT/TDs can bring to organizations and the challenges they face. Several participants have <a href="http://chrismcmahonsblog.blogspot.com/2007/02/bay-area-td-dt-summit-happened.html" title="The Bay Area TD-DT Summit happened">blogged</a> <a href="http://www.spsolutionscorp.com/blog/PermaLink,guid,dc8c28b9-477e-49f0-ba4c-1ffe88129bb7.aspx" title="My take of the Bay Area DT/TD Summit">about</a> the Summit. The discussions continue at </span><a href="http://groups.google.com/group/td-dt-discuss"><span style="font-family:Arial;font-size:100%;">http://groups.google.com/group/td-dt-discuss</span></a><span style="font-family:Arial;font-size:100%;">.</span> </p> </div> <div style="color: rgb(0, 0, 0);"> </div> <ul style="color: rgb(0, 0, 0);"><div> </div><div> </div></ul> <div style="color: rgb(0, 0, 0);"> <p> <span style="font-family:Arial;font-size:100%;">If you spend your days coding and testing, try this opening exercise from the Summit. Imagine that:</span><br /></p> </div> <div style="color: rgb(0, 0, 0);" align="left"> </div> <ul style="color: rgb(0, 0, 0);"><div> </div><div> </div></ul> <div style="text-align: center;"> <span style="font-family:Arial;"><span style="font-size:100%;">T &#8211; &#8211; &#8211; &#8211; &#8211; &#8211; &#8211; &#8211; &#8211; &#8211; D</span></span> <br /></div> <p style="color: rgb(0, 0, 0);"><span style="font-family:Arial;"><span style="font-size:100%;">is a spectrum that has "Tester" at one end and "Developer" at the other. Where would you put yourself, and why? </span></span> </p> <span itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://plus.google.com/116899029375914044550' itemprop='url'/> </span> </script> <noscript> Posted by <span class="mgSecretSpan"><span id="mgSecretSpan_0" class="mgSecretSpan">Harry Robinson,</span></span> Software Engineer in Test <div style="color: rgb(0, 0, 0);"> <p> <span style="font-family:Arial;font-size:100%;">The first-ever industry </span><a href="http://chrismcmahonsblog.blogspot.com/2007/01/announcing-bay-area-developer.html" title="Announcing the Bay Area Developer-Tester/Tester-Developer Summit "><span style="font-family:Arial;font-size:100%;">Developer-Tester/Tester<wbr>-Developer Summit</span></a><span style="font-family:Arial;font-size:100%;"> was held at the Mountain View Googleplex on Saturday, February 24th. Hosted by </span><a href="http://www.testobsessed.com/" target="_blank" title="Elisabeth Hendrickson"><span style="font-family:Arial;font-size:100%;">Elisabeth Hendrickson</span></a><span style="font-family:Arial;font-size:100%;"> and </span><a href="http://chrismcmahonsblog.blogspot.com/" target="_blank" title="Chris McMahon"><span style="font-family:Arial;font-size:100%;">Chris McMahon</span></a><span style="font-family:Arial;font-size:100%;">, the all-day workshop consisted of experience reports and lightning talks including:</span> </p> </div> <div style="color: rgb(0, 0, 0);"> </div> <ul style="color: rgb(0, 0, 0);"><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Al Snow - Form Letter Generator Technique </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Chris McMahon &#8211; Emulating User Actions in Random and Deterministic Modes </span></span> </p> </li><li> <p> <span style="font-family:Arial;font-size:100%;">Dave Liebreich &#8211; Test Mozilla </span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">David Martinez &#8211; Tk-Acceptance </span></span> </p> </li><li> <p> <span style="font-family:Arial;font-size:100%;">Dave W. Smith &#8211; System Effects of Slow Tests</span> </p> </li><li> <p> <span style="font-family:Arial;font-size:100%;"><span class="mgSecretSpan"><span class="mgSecretSpan"><span id="mgSecretSpan_1" class="mgSecretSpan">Harry Robinson</span></span></span> &#8211; <a href="http://model.based.testing.googlepages.com/exploratory-automation.pdf" title="Exploratory Automation">Exploratory Automation</a> </span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Jason Reid &#8211; Not Trusting Your Developers </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Jeff Brown &#8211; MBUnit </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Jeff Fry &#8211; <a href="http://testingjeff.wordpress.com/2007/01/27/creating-methods-on-the-flyand-bugs-in-google-phonebook/" title="Generating Methods on the Fly">Generating Methods on the Fly</a> </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Keith Ray &#8211; ckr_spec </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;">Kurman Karabukaev &#8211; Whitebox testing using Watir </span></span> </p> </li><li> <p> <span style="font-family:Arial;"><span style="font-size:100%;"><span class="mgSecretSpan"><span class="mgSecretSpan">Mark Striebeck</span></span> &#8211; How to Get Developers and Tester to Work Closer Together </span></span> </p> </li><li> <p> <span style="font-family:Arial;font-size:100%;">Sergio Pinon &#8211; UI testing + Cruise Control </span> </p> </li></ul> <ul style="color: rgb(0, 0, 0);"><div> </div></ul> <div style="color: rgb(0, 0, 0);"> <p> <span style="font-family:Arial;font-size:100%;">There were also brainstorming exercises and discussions on the benefits that DT/TDs can bring to organizations and the challenges they face. Several participants have <a href="http://chrismcmahonsblog.blogspot.com/2007/02/bay-area-td-dt-summit-happened.html" title="The Bay Area TD-DT Summit happened">blogged</a> <a href="http://www.spsolutionscorp.com/blog/PermaLink,guid,dc8c28b9-477e-49f0-ba4c-1ffe88129bb7.aspx" title="My take of the Bay Area DT/TD Summit">about</a> the Summit. The discussions continue at </span><a href="http://groups.google.com/group/td-dt-discuss"><span style="font-family:Arial;font-size:100%;">http://groups.google.com/group/td-dt-discuss</span></a><span style="font-family:Arial;font-size:100%;">.</span> </p> </div> <div style="color: rgb(0, 0, 0);"> </div> <ul style="color: rgb(0, 0, 0);"><div> </div><div> </div></ul> <div style="color: rgb(0, 0, 0);"> <p> <span style="font-family:Arial;font-size:100%;">If you spend your days coding and testing, try this opening exercise from the Summit. Imagine that:</span><br /></p> </div> <div style="color: rgb(0, 0, 0);" align="left"> </div> <ul style="color: rgb(0, 0, 0);"><div> </div><div> </div></ul> <div style="text-align: center;"> <span style="font-family:Arial;"><span style="font-size:100%;">T &#8211; &#8211; &#8211; &#8211; &#8211; &#8211; &#8211; &#8211; &#8211; &#8211; D</span></span> <br /></div> <p style="color: rgb(0, 0, 0);"><span style="font-family:Arial;"><span style="font-size:100%;">is a spectrum that has "Tester" at one end and "Developer" at the other. Where would you put yourself, and why? </span></span> </p> <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:Developer-Tester/Tester-Developer Summit&url=https://testing.googleblog.com/2007/03/developer-testertester-developer-summit.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/2007/03/developer-testertester-developer-summit.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'> &#57529; </i> <a href='https://testing.googleblog.com/2007/03/developer-testertester-developer-summit.html#comments' style='font-weight: 500; text-decoration: underline;'>2 comments</a> </div> <div class='post-footer'> <div class='cmt_iframe_holder' data-href='https://testing.googleblog.com/2007/03/developer-testertester-developer-summit.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/Harry%20Robinson' rel='tag'> Harry Robinson </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'> &#59530; </i> </a> <span id='blog-pager-newer-link'> <a class='blog-pager-newer-link' href='https://testing.googleblog.com/search?updated-max=2008-02-25T09:24:00-08:00&max-results=5&reverse-paginate=true' id='Blog1_blog-pager-newer-link' title='Newer Posts'> <i class='material-icons'> &#58820; </i> </a> </span> <span id='blog-pager-older-link'> <a class='blog-pager-older-link' href='https://testing.googleblog.com/search?updated-max=2007-03-12T05:16:00-07:00&max-results=5' id='Blog1_blog-pager-older-link' title='Older Posts'> <i class='material-icons'> &#58824; </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'> &#58821; </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&#39;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'> &#58055; </i> <h2> Archive </h2> <i class='material-icons arrow'> &#58821; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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 collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </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 collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/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'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/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'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/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'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/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'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/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'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/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'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2017/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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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'> &#9658;&#160; </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 expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> &#9660;&#160; </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 expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> &#9660;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/10/'> Oct </a> <span class='post-count' dir='ltr'>(6)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2007/10/tott-avoiding-friend-twister-in-c.html'> TotT: Avoiding friend Twister in C++ </a> </li> <li> <a href='https://testing.googleblog.com/2007/10/automating-tests-vs-test-automation.html'> Automating tests vs. test-automation </a> </li> <li> <a href='https://testing.googleblog.com/2007/10/overview-of-infrastructure-testing.html'> Overview of Infrastructure Testing </a> </li> <li> <a href='https://testing.googleblog.com/2007/10/testing-google-mashup-editor-class.html'> Testing Google Mashup Editor Class </a> </li> <li> <a href='https://testing.googleblog.com/2007/10/performance-testing.html'> Performance Testing </a> </li> <li> <a href='https://testing.googleblog.com/2007/10/post-release-closing-loop_02.html'> Post Release: Closing the loop </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/09/'> Sep </a> <span class='post-count' dir='ltr'>(5)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2007/09/but-it-works-on-my-machine.html'> But it works on my machine! </a> </li> <li> <a href='https://testing.googleblog.com/2007/09/seleniums-inventor.html'> Selenium&#39;s Inventor </a> </li> <li> <a href='https://testing.googleblog.com/2007/09/testing-applications-and-apis.html'> Testing Applications and APIs </a> </li> <li> <a href='https://testing.googleblog.com/2007/09/university-of-arizona-tech-talk.html'> University of Arizona Tech Talk </a> </li> <li> <a href='https://testing.googleblog.com/2007/09/more-feedback-from-google-interns.html'> More feedback from Google Interns </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/08/'> Aug </a> <span class='post-count' dir='ltr'>(3)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2007/08/gtac-videos-now-online.html'> GTAC videos now online </a> </li> <li> <a href='https://testing.googleblog.com/2007/08/gtac-community-thread.html'> GTAC Community Thread </a> </li> <li> <a href='https://testing.googleblog.com/2007/08/abduls-summer-intern-testimonial.html'> Abdul&#39;s Summer Intern Testimonial </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/07/'> Jul </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2007/07/contributing-to-all-star-cast.html'> Contributing to an all-star CAST </a> </li> <li> <a href='https://testing.googleblog.com/2007/07/google-new-york-test-engineering-forum.html'> Google New York Test Engineering Forum July 25 </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/06/'> Jun </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2007/06/gtac-registration-closed.html'> GTAC registration closed </a> </li> <li> <a href='https://testing.googleblog.com/2007/06/tott-extracting-methods-to-simplify.html'> TotT: Extracting Methods to Simplify Testing </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2007/05/sign-up-to-attend-our-test-automation.html'> Sign up to attend our Test Automation Conference </a> </li> <li> <a href='https://testing.googleblog.com/2007/05/8-year-old-exploratory-testing.html'> 8-year-old exploratory testing </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/04/'> Apr </a> <span class='post-count' dir='ltr'>(7)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2007/04/tott-refactoring-tests-in-red.html'> TotT: Refactoring Tests in the Red </a> </li> <li> <a href='https://testing.googleblog.com/2007/04/test-engineering-in-zurich.html'> Test Engineering in Zurich </a> </li> <li> <a href='https://testing.googleblog.com/2007/04/test-engineering-around-world.html'> Test Engineering around the world </a> </li> <li> <a href='https://testing.googleblog.com/2007/04/gtac-speaker-submission-window-closed.html'> GTAC Speaker Submission Window Closed </a> </li> <li> <a href='https://testing.googleblog.com/2007/04/test-engineering-internships.html'> Test Engineering Internships </a> </li> <li> <a href='https://testing.googleblog.com/2007/04/tott-stubs-speed-up-your-unit-tests.html'> TotT: Stubs Speed up Your Unit Tests </a> </li> <li> <a href='https://testing.googleblog.com/2007/04/google-test-automation-conference.html'> Google Test Automation Conference submission deadl... </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://testing.googleblog.com/2007/03/'> Mar </a> <span class='post-count' dir='ltr'>(5)</span> <ul class='posts'> <li> <a href='https://testing.googleblog.com/2007/03/javascript-simulating-time-in-jsunit.html'> TotT: JavaScript: Simulating Time in jsUnit Tests </a> </li> <li> <a href='https://testing.googleblog.com/2007/03/robot-testers-invade-portland_15.html'> Robot testers invade Portland </a> </li> <li> <a href='https://testing.googleblog.com/2007/03/developer-testertester-developer-summit.html'> Developer-Tester/Tester-Developer Summit </a> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </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'> &#9658;&#160; </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_uprR1HtlPeqqLdY8gsNplF6c5GqFLASXpZZtCOArq8MBrESoCwwZdTDnn6V9eGPu2neRyvT8XTHd_Y1gsIInoxC4lPOKMd_5m5ly2Y9HPoqgZ0Tu-K2spnliY74TdCWRUWoeFVmJSBaomij0luKz4=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/&amp;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'] = 'AOuZoY6HBPrGxzA9uNL74dqowBeCPmaVRQ:1732774153939';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d15045980','//testing.googleblog.com/2007/','15045980'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '15045980', 'title': 'Google Testing Blog', 'url': 'https://testing.googleblog.com/2007/', 'canonicalUrl': 'https://testing.googleblog.com/2007/', '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/2fafd358a4bcb2b4', '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': '2007', 'pageTitle': 'Google Testing Blog: 2007'}}, {'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/2007/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': true, 'isLabelSearch': false, 'archive': {'year': 2007, 'rangeMessage': 'Showing posts from 2007'}}}]); _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>

Pages: 1 2 3 4 5 6 7 8 9 10