• 嗯 ,外企确实也受影响了, 微软和谷歌都有裁员的新闻, 前几天跟朋友聊天, sap 也开始裁员了。 在 vmware 的同事也说 hc 比较少。 但应该还是会有坑的,可能就是很少。在范式的同事已经有 3 个去了 vmware 了,大概也就是年前有个同事拿到了 offer。 所以先学起英文做个储备吧,就算以后不去外企,也可以用来辅导孩子的英语。

  • 从上周开始学习英语了, 每天在地铁上听 BBC, 也买了个老友记精讲课程学听力和口语, 好在之前有点底子,12 年左右的时候在硅谷呆过大半年,所以学的不算很吃力。今年 36 岁了,因为国内市场对大龄 IT 人员的不友好,所以我也在焦虑 40 岁以后的发展。 初步的想法是尽量延长自己的职业生涯,所以除了要学习技术外, 也开始学习英语。 为以后进外企做准备(外企不是很看重年龄,如果哪天被公司裁了,就可以考虑去外企试试了)。

    感觉行业状态越是低迷, 就越不能放弃自己吧, 尽量的在茫茫众生中杀出一条血路。 当然也有人说以后外企什么样子还不知道呢,现在就花这么大精力学外语可能到最后毛用都没有。 我觉得也许会这样吧,很多时候我学习一样东西的时候其实也不确定以后是不是真的能派上用场。 但书到用时方恨少,等真到需要用的时候才开始学习就已经晚了。 所以我的习惯都是先学了再说,学总比不学要好,没准哪天就真用到了。

  • 谈一谈今年的 TesterHome at 2022年11月29日

    可能会有这方面的因素吧。 总结一下我最这一年的技术积累也变少了。 不过我最近没写帖子的原因是因为正在写书。。。实在抽不出时间写帖子了。

  • 聊一些对测试技术的看法 at 2022年09月26日

    这个事怎么说呢。 测试一个产品的前提得是能理解这个产品,成为这个产品的用户对吧。 如果都没有能力成为这个产品的用户当然也就没法设计测试用例了。 就好比一个人作为车场的质检人员。 但是他本身不会开车,也不懂车里的任何设备。那是测不了的。 不管设计这个车的所谓的产品经理有多强, 他也没办法能让一个根本没开过车的人能测试的了这辆车的。

    同样,B 端的产品也是这样的道理。 就拿我现在负责的产品来说。 主要是分为两种产品,一种是基于 K8S 的商业化云产品,一种是基于深度学习和机器学习的 AI 平台。这两者都不是给普通人用的。前者需要测试人员懂 docker,k8s 这些虚拟化领域的专业知识, 后者需要测试人员懂得人工智能的基本业务流程。要不然是测试不了的,你连产品经理在说什么都听不明白的。

  • 聊一些对测试技术的看法 at 2022年09月26日

    那我后面还真 要高低买个 p5 玩一下了。

  • 聊一些对测试技术的看法 at 2022年09月21日

    那好像比较适合现在的我啊。后面我还想 看看 p5 啥样。 看开端的时候卢迪说 p5 天下第一。 我想感受感受。 虽然目前 我玩的游戏里还是塞尔达最好

  • 聊一些对测试技术的看法 at 2022年09月20日

    哈哈哈哈哈哈。 我看你最近 还是在玩怪猎么。 我刚买了奶刃 3,但是玩不进去。 感觉 switch 后面有好多好游戏啊。 P5 也要移植到 switch 了。

  • 聊一些对测试技术的看法 at 2022年09月19日

    这个分情况的。你看到的互联网大厂里一些 QA 分享的各种平台和轮子都是个例。 能有机会去做这些事情的毕竟是少部分。 大部分人还是把精力都放在了业务测试上的。而 C 端业务大多是给普通人用的,所以技术含量偏低。 而 B 端业务大部分是给专业人用的。所以即便不去造一些平台和轮子。其专业技能的要求也比 C 端的大部分岗位要高

  • 不焦虑了,谢谢大家 at 2022年09月16日

    其实讲道理,我觉得我给的建议可能不太有用😂 ,咱们的经历相差太多了。 这种情况下给你的建议可能都是不适合你的。 有些时候真得是自己想通了,开窍了最重要。 其他人的建议大多数都帮不上啥。

  • 直觉上,应该是楼主的学历拖了后腿了。 如果是本科毕业的话,懂得这些东西在深圳 12K 确实低了。 最近其实应该各个大佬都不会建议你跳槽吧。 现在的大环境太差了。

  • 聊一些对测试技术的看法 at 2022年09月16日

    嗯嗯, 你这样的心态我觉得挺好的

  • 聊一些对测试技术的看法 at 2022年09月16日

    你问的这几个问题我觉得我也答不好。 其实我很少去思考这些问题。我都是把眼下团队里的问题解决掉就好。 我很少考虑什么自动化的本质是什么这样的问题。 我只要判断自动化是不是在我当前团队里有用的, 有就搞, 没有就不搞。

  • 聊一些对测试技术的看法 at 2022年09月16日

    测试

  • 因为丧。 所以现在有点不务正业~~~ 好久没写书了,也没啥动力学习,工作上一忙完就打游戏了。 而且还必须是打不用费脑子的游戏, 我最近真的是大脑疲劳了。 奶刃 3 买了以后仍在那碰都不想碰。 那个复杂的战斗系统和剧情太烧脑。

  • 我没说你啊。 我说的楼主是 maimai 里发帖子的那个楼主

  • 最近有点丧, 一直没管工作之外的事。其实很早之前我就在 maimai 上看到这个职言了,当时我还发群里给恒温他们看。 但我们一直也没管,毕竟人家有发表自己看法的权利。 那现在我来说一下自己的想法吧。

    关于过于极端的观点

    怎么说呢,我一直觉得国人非常容易陷入某种特别极端的观点中,从这个职言中其实可以看出来楼主和部分其他人已经陷入了什么观点都听不进去,只认为自己是对的这种极端情绪中了。 之所以说极端,是因为好多人都觉得社区的大会全部都是落不了地的平台轮子,就没有一个是有用的。 这话明显就太极端了。老实说关于炫技,落地困难的情况有没有?那肯定是有的,要说一点都没有我相信社区自己也不信。 但讲道理,所有议题全是炫技和无法落地的东西。 这话说出来,不觉得莫名其妙么,我也不怕得罪人,有些议题觉得无法落地可能确实是过于偏门了,也确实有讲师为了体现技术含量而过于设计了,但有些时候可能单纯的就是你没听懂这个议题,你不懂的东西当然觉的无法落地。就是我参加议题评审的时候,遇到不属于我所在领域的议题的时候,我一般也都是闭嘴的,这些议题在我看来也没办法落地,但这只是单纯的我不懂,人家 PPT 里讲了一堆视频领域的指标,我以前压根就没听过,这是很正常的事。而且炫技这事有这么不能理解么?咱们出去面试,在公司搞晋升搞分享,哪个不炫点技?搞一些平平无奇的东西面试能成功么?晋升能成功么?大家问问自己,自己去面试和晋升的时候,是不是也得挑技术含量高的说?所以讲师出来分享议题的时候,稍微包装包装,挑一些有技术含量的东西来展示展示自己的能力,这个其实无可厚非。大家还是不要过于双标,严于律人,宽于律己。

    关于无法落地

    关于能不能落地这事其实很主观的,上面我也说过确实有议题和讲师为了炫技搞了一些过于设计的东西。也有些议题很冷门,很小众。 但其实大部分时候,对于我来说,能不能落地的前提在于我是不是已经涉足了这个领域了, 是不是在这个领域里已经积累到一定程度了。 也只有我自己在这方面有很长时间的研究后,我才能分辩出这个议题是不是靠谱,在落地过程中会有什么重点的困难, 这些困难讲师有没有说到。 我在评审议题的时候,遇到我擅长领域的议题都是能看出来讲师是不是在胡扯的,甚至我能判断出来讲师是不是真的做过这块内容,是不是在拿其他人的成果在这里充数。 因为外行人是蒙不了真正在这方面研究过几年的专业人员的。这一次议题评审的时候有个测试 AI 产品的议题,我一上来就说了这个人应该不是专业做 AI 的,他 PPT 里的内容都是拿别人做的东西拼凑出来的,思路非常混乱,而且关键的问题全都被他回避了。 只有拥有这样一些该领域的专业能力以后,很多议题才对我来说是可以落地的。 因为听议题听的是思路,而不是实现方式。如果大会对讲师的要求是在 40 分钟内让 0 基础的人能回去直接落地的程度,那就没讲师能通过审核了,因为那得是神一样的语言精练能力啊。 大家想想,学生时代的时候学个 java 还得一个学期的时间呢, 要是谁能 40 分钟讲一遍就能让学生自己去实践项目了。那培训机构就可以都倒闭了。 很多时候当你有这个能力基础的时候,真的是听一遍思路就知道怎么回事了。 你就可以判断出来这个议题对自己有没有价值, 我回去以后要怎么针对这个思路来定制化我自己的场景。

    最后说说关于听大会的姿势

    • 首先对于任何一个人来说,大会中的议题中绝大部分对你都是没有什么用的。 这一点我觉得大家要达成共识。就像对于我来说,AI,大数据,容器,混沌工程之外的所有议题对我来说都是看个热闹。为什么? 因为不管讲的多好我也用不上,我就没那个需求。 大会一定是尽量包含更多领域的内容的,所以预期上还是要管理好的。
    • 尽量挑自己擅长的领域内去听。不要因为这个技术比较新就去听, 因为去了可能也是听的云里雾里的。真的,很多议题我都觉得如果不是专业人士,去听了就是浪费时间的,吸收不到什么有用信息的。
    • 一定要预习,你想听这个议题。在事前就去搜这个议题的相关资料,否则就还是听的云里雾里的。真的就是除非你在这个提议场景里本身就非常专业了, 否则在没有准备的情况下去听,肯定是效果很差的。 换谁也不可能在 40 分钟里把前因后果全都明明白白的讲清楚的。 讲师在分享的时候,有个预设条件就是很多基础知识听众是懂的。 比如要是我去分享混沌工程的东西,那我一定预设听众起码对一些开源的故障注入工具,以及 docker,k8s 还有一些通用的高可用设计是了解的。否则光是讲一个高可用设计中的数据同步这么一个小点,你给我 40 分钟我可能都讲不完。
  • 这么快就来查资料了😄

  • k8s 集群监控平台的实现 at 2022年07月26日

    暂时没开源哈

  • mock server 实践 at 2022年06月23日

    我一个一个回答一下:

    1. mockserver 不是注入在 initcontainer 里的。是注入到 pod 里的一个单独的容器 。 initcontainer 只负责修改 iptables。 mockserver 容器则启动 mock 服务。
    2. 这个是 iptables 的规则。 你看我在设置规则的时候使用的是 prerouting 这个链。 如果网络包是从本主机发送出去的。 是不经过这个链的。只有外面的流量进入本主机的时候,才会经过这个链。 所以这个规则可以成功把外面发送给服务的流量转发给 mockserver,而 mockserver 本身发送给服务请求不会被这个规则拦截(mockserver 容器和服务容器都是在 Pod 中的,在 k8s 中同一个 pod 中的所有容器共用同一个网络名称空间。所以对于目标服务来说,mockserver 容器其实就是本机网络)。所以不会造成死循环。 具体的规则你看一下我下面在网上找的文章的截图:

  • 明年~

  • 很久没发帖了,聊聊 at 2022年06月05日

    好久不见,牛哥现在这么强了

  • 测开 offer 求比较 at 2022年05月16日
    仅楼主可见
  • 测试

  • allure report 可以直接启动一个 web 服务而不是静态的 html 文件。 测试用例的执行情况都在 http 的接口里。 可以直接抓。 我们之前的做法是在 jenkins 的 share lib 里写了抓取 allure report 结果的脚本。 然后在 pipeline 里直接调用即可。代码如下:

    import groovy.grape.Grape
    
    
    /**
     * Created by sungaofei on 19/3/1.
     */
    
    @Grab(group = 'org.codehaus.groovy.modules.http-builder', module = 'http-builder', version = '0.7')
    @Grab(group = 'org.jsoup', module = 'jsoup', version = '1.10.3')
    import org.jsoup.Jsoup
    import groovyx.net.http.HTTPBuilder
    
    
    import static groovyx.net.http.ContentType.*
    import static groovyx.net.http.Method.*
    import groovy.transform.Field
    
    //可以指定maven仓库
    //@GrabResolver(name = 'aliyun', root = 'http://maven.aliyun.com/nexus/content/groups/public/')
    //加载数据库连接驱动包
    //@Grab('mysql:mysql-connector-java:5.1.25')
    //@GrabConfig(systemClassLoader=true)
    
    //global variable
    @Field jenkinsURL = "http://k8s.testing-studio.com:5003"
    
    @Field int passed
    @Field int failed
    @Field int skipped
    @Field int broken
    @Field int unknown
    @Field int total
    @Field Map<String, Map<String, Integer>> map = new HashMap<>()
    
    @NonCPS
    def getResultFromAllure() {
        def reportURL = "/job/DailyBuild/${BUILD_NUMBER}/allure/"
    
    //    if (env.BRANCH_NAME != "" && env.BRANCH_NAME != null) {
    //        reportURL = "http://k8s.testing-studio.com:5003/job/Daily%20Build/allure/"
    //    } else {
    //        reportURL = "/view/API/job/${JOB_NAME}/${BUILD_NUMBER}/allure/"
    //    }
    
    //    reportURL = "/view/API/job/sage-sdk-test/185/allure/"
        println(jenkinsURL+"${reportURL}widgets/summary.json")
    
        HTTPBuilder http = new HTTPBuilder("http://k8s.testing-studio.com:5003")
        //根据responsedata中的Content-Type header,调用json解析器处理responsedata
        http.get(path: "${reportURL}widgets/summary.json") { resp, json ->
            println resp.status
            passed = Integer.parseInt((String) json.statistic.passed)
            failed = Integer.parseInt((String) json.statistic.failed)
            skipped = Integer.parseInt((String) json.statistic.skipped)
            broken = Integer.parseInt((String) json.statistic.broken)
            unknown = Integer.parseInt((String) json.statistic.unknown)
            total = Integer.parseInt((String) json.statistic.total)
        }
    
    
    }
    
    
    def call() {
        getResultFromAllure()
    
        getDatabaseConnection(type: 'GLOBAL') {
    //        map.each { feature, valueMap ->
    //            def sqlString = "INSERT INTO func_test (name, build_id, feature, version, total, passed, unknown, skipped, failed, broken, create_time) VALUES ('${JOB_NAME}', '${BUILD_ID}', '${feature}', '${version}', " +
    //                    "${valueMap['total']}, ${valueMap['passed']}, ${valueMap['unknown']}, ${valueMap['skipped']}, ${valueMap['failed']}, ${valueMap['broken']}, NOW())"
    //            println(sqlString)
    //
    //            sql sql: sqlString
    //        }
    
    //        def lineCov = 0
    //        def branchCov = 0
    //        if (coverage != null && coverage != ""){
    //            lineCov = getLineCov()
    //            branchCov = getBranchCov() * 100
    //
    //        }
    
            def sqlString = "INSERT INTO func_test_summary (name, build_id, total, passed, unknown, skipped, failed, broken, create_time) VALUES ('${JOB_NAME}', '${BUILD_ID}', " +
                    "${total}, ${passed}, ${unknown}, ${skipped}, ${failed}, ${broken}, NOW())"
    
            sql sql: sqlString
    
        }
    }
    
  • 测试