存档

‘Linux自动化运维’ 分类的存档

自动化测试的7个步骤

2017年4月17日 评论已被关闭

自动化测试的7个步骤

http://blog.sina.com.cn/s/blog_4aae007d0100s18h.html

【摘要】我们对自动化测试充满了希望,然而,自动化测试却经常带给我们沮丧和失望。虽然,自动化测试可以把我们从困难的环境中解放出来,在实施自动化测试解决问题的同时,又带来同样多的问题。在开展自动化测试的工作中,关键问题是遵循软件开发的基本规则。本文介绍自动化测试的 7 个步骤:改进自动化测试过程,定义需求,验证概念,支持产品的可测试性,具有可延续性的设计( design for sustainability ),有计划的部署和面对成功的挑战。按照以上 7 个步骤,安排你的人员、工具和制定你的自动化测试项目计划,你将会通往一条成功之路。
一个故事 :
我在很多软件公司工作过,公司规模有大有小,也和来自其他公司的人员交流,因此经历过或者听说过影响自动化测试效果的各种各样的的问题。本文将提供若干方法规避可能在自动化测试中出现的问题。我先给大家讲一个故事,以便各位了解自动化测试会出现哪些问题。
以前,我们有一个软件项目,开发小组内所有的人都认为应该在项目中采用自动化测试。软件项目的经理是 Anita Delegate 。她评估了所有可能采用的自动化测试工具,最后选择了一种,并且购买了几份拷贝。她委派一位员工 ——Jerry Overworked 负责自动化测试工作。 Jerry 除了负责自动化测试工作,还有其他的很多任务。他尝试使用刚刚购买的自动化测试工具。当把测试工具应用到软件产品测试中的时候,遇到了问题。这个测试工具太复杂,难于配置。他不得不给测试工具的客户支持热线打了几个电话。最后, Jerry 认识到,他需要测试工具的技术支持人员到现场帮助安装测试工具,并找出其中的问题。在打过几个电话后,测试工具厂商派过来一位技术专家。技术专家到达后,找出问题所在,测试工具可以正常工作了。这还算是顺利了。但是,几个月后,他们还是没有真正实现测试自动化, Jerry 拒绝继续从事这个项目的工作,他害怕自动化测试会一事无成,只是浪费时间而已。
项目经理 Anita 把项目重新指派给 Kevin Shorttimer ,一位刚刚被雇佣来做软件测试的人员。 Kevin 刚刚获得计算机科学的学位,希望通过这份工作迈向更有挑战性的、值得去做的工作。 Anita 送 Kevin 参加工具培训,避免 Kevin 步 Jerry 的后尘 —— 由于使用测试工具遇到困难而变得沮丧,导致放弃负责的项目。 Kevin 非常兴奋。这个项目的测试需要重复测试,有点令人讨厌,因此,他非常愿意采用自动化测试。一个主要的版本发布后, Kevin 准备开始全天的自动化测试,他非常渴望得到一个机会证明自己可以写非常复杂的,有难度的代码。他建立了一个测试库,使用了一些技巧的方法,可以支持大部分的测试,这比原计划多花费了很多时间,不过, Kevin 使整个测试工作开展的很顺利。他用已有的测试套测试新的产品版本,并且确实发现了 bug 。接下来, Kevin 得到一个从事软件开发职位的机会,离开了自动化的岗位。
Ahmed Hardluck 接手 Kevin 的工作,从事自动化测试执行工作。他发现 Kevin 留下的文档不仅少,并且没有太多的价值。 Ahmed 花费不少时间去弄清楚已有的测试设计和研究如何开展测试执行工作。这个过程中, Ahmed 经历了很多失败,并且不能确信测试执行的方法是否正确。测试执行中,执行失败后的错误的提示信息也没有太多的参考价值,他不得不更深的钻研。一些测试执行看起来仿佛永远没有结束。另外一些测试执行需要一些特定的测试环境搭建要求,他更新测试环境搭建文档,坚持不懈地工作。后来,在自动化测试执行中,它发现几个执行失败的结果,经过分析,是回归测试的软件版本中有 BUG ,导致测试执行失败,发现产品的 BUG 后,每个人都很高兴。接下来,他仔细分析测试套中的内容,希望通过优化测试套使测试变得更可靠,但是,这个工作一直没有完成,预期的优化结果也没有达到。按照计划,产品的下一个发布版本有几个主要的改动, Ahmed 立刻意识到产品的改动会破坏已有的自动化测试设计。接下来,在测试产品的新版本中,绝大多数测试用例执行失败了, Ahmed 对执行失败的测试研究了很长时间,然后,从其他人那里寻求帮助。经过商讨,自动化测试应该根据产品的新接口做修改,自动化测试才能运转起来。最后,大家根据新接口修改自动化测试,测试都通过了。产品发布到了市场上。接下来,用户立刻打来投诉电话,投诉软件无法工作。大家才发现自己改写了一些自动化测试脚本,导致一些错误提示信息被忽略了。虽然,实际上测试执行是失败的,但是,由于改写脚本时的一个编程错误导致失败的测试执行结果被忽略了。这个产品终于失败了。
这是我的故事。或许您曾经亲身经历了故事当中某些情节。不过,我希望你没有这样的相似结局。本文将给出一些建议,避免出现这样的结局。
问题
这个故事阐明了几个使自动化测试项目陷入困境的原因:
自动化测试时间不充足:根据项目计划的安排,测试人员往往被安排利用自己的个人时间或者项目后期介入自动化测试。这使得自动化测试无法得到充分的时间,无法得到真正的关注。
缺乏清晰的目标:有很多好的理由去开展自动化测试工作,诸如自动化测试可以节省时间,使测试更加简单,提高测试的覆盖率,可以让测试人员保持更好的测试主动性。但是,自动化测试不可能同时满足上述的目标。不同的人员对自动化测试有不同的希望,这些希望应该提出来,否则很可能面对的是失望。
缺乏经验:尝试测试自己的程序的初级的程序员经常采用自动化自动化测试。由于缺乏经验,很难保证自动化测试的顺利开展。
更新换代频繁( High turnover ):测试自动化往往需要花费很多时间学习的,当自动化测试更新换代频繁的时候,你就丧失了刚刚学习到的自动化测试经验。
对于绝望的反应:在测试还远没有开始的时候,问题就已经潜伏在软件中了。软件测试不过是发现了这些潜伏的问题而已。就测试本身而言,测试是一件很困难的工作。当在修改过的软件上一遍接一遍的测试时,测试人员变得疲劳起来。测试什么时候后结束?当按照计划的安排,软件应该交付的时候,测试人员的绝望变得尤其强烈。如果不需要测试,那该有多好呀!在这种环境中,自动化测试可能是个可以选择的解决方法。但是,自动化测试却未必是最好的选择,他不是一个现实的解决方法,更像是一个希望。
不愿思考软件测试:很多人发现实现产品的自动化测试比测试本身更有趣。在很多软件项目发生这样的情况,自动化工程师不参与到软件测试的具体活动中。由于测试的自动化与测试的人为割裂,导致很多自动化对软件测试并没有太大的帮助。
关注于技术:如何实现软件的自动化测试是一个很吸引人的技术问题。不过,过多的关注如何实现自动化测试,导致忽略了自动化测试方案是否符合测试需要。
遵守软件开发的规则
你可能了解 SEI (软件工程研究所)提出的 CMM (能力成熟度模型)。 CMM 分为 5 个界别,该模型用来对软件开发组织划分等级。 Jerry Weinberg (美国著名软件工程专家)也创建了自己的一套软件组织模型,在他的组织模型中增加了一个额外的级别,他称之为零级别。很显然,一个零模式的组织实际上也是开发软件;零模式组织中,在开发人员和用户之间没有差别 [Weinberg 1992] 。恰恰在这类组织环境中,经常采用自动化测试方法。因此,把资源用于自动化测试,并且把自动化测试当作一个软件开发活动对待,把软件测试自动化提升到一级。这是解决测试自动化的核心的方案。我们应该像运作其他的开发项目一样来运作软件自动化测试项目。
像其他软件开发项目一样,我们需要软件开发人员专注于测试自动化的开发任务;像其他软件开发项目一样,自动化测试可以自动完成具体的测试任务,对于具体的测试任务来说,自动化开发人员可能不是这方面的专家,因此,软件测试专家应该提供具体测试任务相关的咨询,并且提供测试自动化的需求;像其他软件开发项目一样,如果在开发编码之前,对测试自动化作了整体设计有助于测试自动化开发的顺利开展。像其他软件开发项目一样,自动化测试代码需要跟踪和维护,因此,需要采用源代码管理。像其他软件开发项目一样,测试自动化也会出现 BUG ,因此,需要有计划的跟踪 BUG ,并且对修改后的 BUG 进行测试。像其他软件开发项目一样,用户需要知道如何使用软件,因此,需要提供用户使用手册。
本文中不对软件开发做过多讲述。我假定您属于某个软件组织,该组织已经知道采用何种合理的、有效的方法开发软件。我仅仅是推动您在自动化测试开发过程中遵守已经建立的软件开发规则而已。本文按照在软件开发项目中采用的标准步骤组织的,重点关注测试自动化相关的事宜和挑战。
·改进软件测试过程
·定义需求
·验证概念
·支持产品的可测试性
·可延续性的设计( design for sustainability )
·有计划的部署
·面对成功的挑战
步骤一:改进软件测试过程
如果你负责提高一个商业交易操作的效率,首先,你应该确认已经很好的定义了这个操作的具体过程。然后,在你投入时间和金钱采用计算机提供一套自动化的商业交易操作系统之前,你想知道是否可以采用更简单、成本更低的的方法。同样的,上述过程也是用于自动化测试。我更愿意把 “ 测试自动化 ” 这个词解释成能够使测试过程简单并有效率,使测试过程更为快捷,没有延误。运行在计算机上的自动化测试脚本只是自动化测试的一个方面而已。
例如,很多测试小组都是在回归测试环节开始采用测试自动化的方法。回归测试需要频繁的执行,再执行,去检查曾经执行过的有效的测试用例没有因为软件的变动而执行失败。回归测试需要反复执行,并且单调乏味。怎样才能做好回归测试文档化的工作呢?通常的做法是采用列有产品特性的列表,然后对照列表检查。这是个很好的开始,回归测试检查列表可以告诉你应该测试哪些方面。不过,回归测试检查列表只是合于那些了解产品,并且知道需要采用哪种测试方法的人。
在你开始测试自动化之前,你需要完善上面提到的回归测试检查表,并且,确保你已经采用了确定的的测试方法,指明测试中需要什么样的数据,并给出设计数据的完整方法。如果测试掌握了基本的产品知识,这会更好。确认可以提供上面提到的文档后,需要明确测试设计的细节描述,还应该描述测试的预期结果,这些通常被忽略,建议测试人员知道。太多的测试人员没有意识到他们缺少什么,并且由于害怕尴尬而不敢去求助。这样一份详细的文档给测试小组带来立竿见影的效果,因为,现在任何一个具有基本产品知识的人根据文档可以开展测试执行工作了。在开始更为完全意义上的测试自动化之前,必须已经完成了测试设计文档。测试设计是测试自动化最主要的测试需求说明。不过,这时候千万不要走极端去过分细致地说明测试执行的每一个步骤,只要确保那些有软件基本操作常识的人员可以根据文档完成测试执行工作既可。但是,不要假定他们理解那些存留在你头脑中的软件测试执行的想法,把这些测试设计的思路描述清楚就可以了。
我以前负责过一个软件模块的自动化测试工作。这个模块的一些特性导致实现自动化非常困难。当我了解到这项工作无需在很短的时间内完成后,决定制定一个详细回归测试设计方案。我仔细地检查了缺陷跟踪库中与该模块相关的每个已经关闭的缺陷,针对每个缺陷,我写了一个能够发现该问题的测试执行操作。我计划采用这种方法提供一个详细的自动化需求列表,这可以告诉我模块的那一部分最适合自动化测试。在完成上述工作后,我没有机会完成测试自动化的实现工作。不过,当我们需要对这个模块做完整回归测试的时候,我将上面提到的文档提供给若干只了解被测试产品但是没有测试经验的测试人员。依照文档的指导,几乎不需要任何指导的情况下,各自完成了回归测试,并且发现了 BUG 。从某种角度看,这实际上是一次很成功的自动化测试。在这个项目中,我们与其开发自动化测试脚本,还不如把测试执行步骤文档化。后来,在其它项目中,我们开发了自动化测试脚本,发现相关人员只有接受相关培训才能理解并执行自动化测试脚本,如果测试自动化设计的很好,可能会好一些。不过,经过实践我们总结出完成一份设计的比较好的测试文档,比完成一份设计良好的测试脚本简单的多。
另外一个提高测试效率的简单方法是采用更多的计算机。很多测试人员动辄动用几台计算机,这一点显而易见。我之所以强调采用更多的计算机是因为,我曾经看到一些测试人员被误导在单机上努力的完成某些大容量的自动化测试执行工作,这种情况下由于错误的使用了测试设备、测试环境,导致测试没有效果。因此,自动化测试需要集中考虑所需要的支撑设备。
针对改进软件测试过程,我的最后一个建议是改进被测试的产品,使它更容易被测试,有很多改进措施既可以帮助用户更好的使用产品,也可以帮助测试人员更好的测试产品。稍后,我将讨论自动化测试的可测试需求。这里,我只是建议给出产品的改进点,这样对手工测试大有帮助。
一些产品非常难安装,测试人员在安装和卸载软件上花费大量的时间。这种情况下,与其实现产品安装的自动化测试,还不如改进产品的安装功能。采用这种解决办法,最终的用户会受益的。另外的一个处理方法是考虑开发一套自动安装程序,该程序可以和产品一同发布。事实上,现在有很多专门制作安装程序的商用工具。
另一些产品改进需要利用工具在测试执行的日志中查找错误。采用人工方法,在日志中一页一页的查询报错信息很容易会让人感到乏味。那么,赶快采用自动化方法吧。如果你了解日志中记录的错误信息格式,写出一个错误扫描程序是很容易的事情。如果,你不能确定日志中的错误信息格式,就开始动手写错误扫描程序,很可能面临的是一场灾难。不要忘记本文开篇讲的那个故事中提到的测试套无法判断测试用例是否执行失败的例子。最终用户也不愿意采用通过搜索日志的方法查找错误信息。修改错误信息的格式,使其适合日志扫描程序,便于扫描工具能够准确的扫描到所有的错误信息。这样,在测试中就可以使用扫描工具了。
通过改进产品的性能对测试也是大有帮助的。很显然的,如果产品的性能影响了测试速度,鉴别出性能比较差的产品功能,并度量该产品功能的性能,把它作为影响测试进度的缺陷,提交缺陷报告。
上面所述的几个方面可以在无需构建自动化测试系统的情况下,大幅度的提高测试效率。改进软件测试过程会花费你构建自动化测试系统的时间,不过改进测试过程无疑可以使你的自动化测试项目更为顺利开展起来。
步骤二:定义需求
在前面的故事中,自动化工程师和自动化测试的发起者的目标存在偏差。为了避免这种情况,需要在自动化测试需求上保持一致。应该有一份自动化测试需求,用来描述需要测试什么。测试需求应该在测试设计阶段详细描述出来,自动化测试需求描述了自动化测试的目标。很多人认为自动化测试显然是一件好事情,但是,他们不愿意对自动化测试的目标给出清晰的描述。下面是人们选用自动化测试的几个原因:
·加快测试进度从而加快产品发布进度
·更多的测试
·通过减少手工测试降低测试成本
·提高测试覆盖率
·保证一致性
·提高测试的可靠性
·测试工作可以由技术能力不强测试人员完成
·定义测试过程,避免过分依赖个人
·测试变得更加有趣
·提高了编程技能
开发管理、测试管理和测试人员实现自动化测试的目标常常是有差别的。除非三者之间达成一致,否则很难定义什么是成功的自动化测试。
当然,不同的情况下,有的自动化测试目标比较容易达到,有的则比较难以达到。测试自动化往往对测试人员的技术水平要求很高,测试人员必须能理解充分的理解自动化测试,从而通过自动化测试不断发现软件的缺陷。不过,自动化测试不利于测试人员不断的积累测试经验。不管怎么样,在开始自动化测试之前应该确定自动化测试成功的标准。
手工测试人员在测试执行过程中的一些操作能够发现不引人注意的问题。他们计划并获取必要的测试资源,建立测试环境,执行测试用例。测试过程中,如果有什么异常的情况发生,手工测试人员立刻可以关注到。他们对比实际测试结果和预期测试结果,记录测试结果,复位被测试的软件系统,准备下一个软件测试用例的环境。他们分析各种测试用例执行失败的情况,研究测试过程可疑的现象,寻找测试用例执行失败的过程,设计并执行其他的测试用例帮助定位软件缺陷。接下来,他们写作缺陷报告单,保证缺陷被修改,并且总结所有的缺陷报告单,以便其他人能够了解测试的执行情况。
千万不要强行在测试的每个部分都采用自动化方式。寻找能够带来最大回报的部分,部分的采用自动化测试是最好的方法。或许你可能发现采用自动化执行和手动确认测试执行结果的方式是个很好的选择,或许你可以采用自动化确认测试结果和手工测试执行相结合和方式。我听到有人讲,除非测试的各个环节都采用自动化方式,否则不是真正意义上的自动化测试,这真是胡言乱语。如果仅仅是为了寻找挑战,可以尝试在测试的每个环节都采用自动化方法。但是,如果寻找成功测试的方法,请关注那些可以快速建立的,可以反复利用的自动化测试。
定义自动化测试项目的需求要求我们全面地、清楚地考虑各种情况,然后给出权衡后的需求,并且可以使测试相关人员更加合理的提出自己对自动化测试的期望。通过定义自动化测试需求,距离成功的自动化测试近了一步。
步骤三:验证概念
在前面的故事当中,那个自动化测试人员在对测试方向一片茫然的情况下一头扎进了自动化测试项目中。不过,在项目的进行中,他得到了来自各个方面的支持。
你可能还没有认识到这一点,不过,你必须验证自动化测试项目的可行性。验证过程花费的时间往往比人们预期的要长,并且需要来自你身边的各种人的帮助。
很多年前,我从事一个测试自动化项目的工作,参加项目的人员有各种各样的好点子。我们设计了一个复杂的自动化测试系统,并且非常努力工作去实现系统的每个模块。我们定期的介绍测试自动化的设计思路和工作进度,甚至演示已经完成的部分功能。但是,我们没有演示如何利用该套测试自动化系统如何开展实际的测试工作。最后,整个项目被取消了,此后,我再也没有犯这个错误。
你需要尽可能快地验证你采用的测试工具和测试方法的可行性,站在产品的角度验证你所测试的产品采用自动化测试的可行性。这通常是很困难的,需要尽快地找出可行性问题的答案,需要确定你的测试工具和测试方法对于被测试的产品和测试人员是否合适。你需要做是验证概念 —— 一个快速、有说服力的测试套可以证明你选在测试工具和测试方法的正确性,从而验证了你的测试概念。你选择的用来验证概念的测试套是评估测试工具的最好的方式。
对于很多人来说,自动化测试意味着 GUI 自动化测试,我不同意这种观点。我曾经做过 GUI 和非 GUI 自动化测试,并惊奇的发现这两类测试的测试计划有很大的互补性。不过, GUI 测试工具很昂贵、并且过分讲究。选择合适的 GUI 测试工具是很重要的,因为,如果没有选择合适的测试工具,你会遇到很多不可预测的困难。 Elisabeth Hendrickson 曾经写过一篇关于选择测试的工具的指导性文章 [Hendrickson 1999] 。我建议在评估测试工具中,找出能够验证你的想法的证据是很重要的环节。这需要测试工具至少有一个月试用期,你可能打算现在购买一份测试工具,然后直到评估完成后再购买更多份。你需要在付出大笔金钱购买测试工具的之前,找出工具存在的问题。这样,你可以从测试工具供应商得到更好的帮助,当你打算更换工具的时候,你不会感觉很为难。
下面是一些候选的验证概念的试验:
回归测试:你准备在每个版本运行同样的测试用例吗?回归测试是最宜采用自动化测试的环节。
配置测试:你的软件支持多少种不同的平台?你打算在所有支持的平台上测试执行所有的测试用例吗?如果是的,那么采用自动化测试是有帮助的。
测试环境建立:对于大量不同的测试用例,可能需要相同的测试环境搭建过程。在开展自动化测试执行之前,先把测试环境搭建实现自动化。
非 GUI 测试:实现命令行和 API 的测试自动化比 GUI 自动化测试容易的多。
无论采用什么测试方法,定义一个看得见的目标,然后集中在这个目标上。验证你自动化测试概念可以使自动化更进一步迈向成功之路。
步骤四:支持产品的可测试性
软件产品一般会用到下面三种不同类别的接口:命令行接口( command line interfaces ,缩写 CLIs) 、应用程序接口( API )、图形用户接口( GUI )。有些产品会用到所有三类接口,有些产品只用到一类或者两类接口,这些是测试中所需要的接口。从本质上看, API 接口和命令行接口比 GUI 接口容易实现自动化,去找一找你的被测产品是否包括 API 接口或者命令行接口。有些时候,这两类接口隐藏在产品的内部,如果确实没有,需要鼓励开发人员在产品中提供命令行接口或者 API 接口,从而支持产品的可测试性。
下面,更多多的讲解 GUI 自动化测试相关内容。这里有几个原因导致 GUI 自动化测试比预期的要困难。第一个原因是需要手工完成部分脚本。绝大多数自动化测试工具都有 “ 录制回放 ” 或者 “ 捕捉回放 ” 功能,这确实是个很好的方法。可以手工执行测试用例,测试工具在后台记住你的所有操作,然后产生可以用来重复执行的测试用例脚本。这是一个很好的方法,但是很多时候却不能奏效。很多软件测试文章的作者得出结论 “ 录制回放 ” 虽然可以生成部分测试脚本,但是有很多问题导致 “ 录制回放 ” 不能应用到整个测试执行过程中。 [Bach 1996, Pettichord 1996, Kaner 1997, Linz 1998, Hendrickson 1999, Kit 1999, Thomson 1999, Groder 1999]. 结果, GUI 测试还是主要由手工完成。
第二个原因,把 GUI 自动化测试工和被测试的产品有机的结合在一起需要面临技术上的挑战。经常要在采用众多专家意见和最新的 GUI 接口技术才能使 GUI 测试工具正常工作。这个主要的困难也是 GUI 自动化测试工具价格昂贵的主要原因之一。非标准的、定制的控件会增加测试的困难,解决方法总是有的,可以采用修改产品源代码的方式,也可以从测试工具供应商处升级测试工具。另外,还需要分析测试工具中的 BUG ,并且给工具打补丁。也可能测试工具需要做相当的定制,以便能有效地测试产品界面上的定制控件。 GUI 测试中,困难总是意外出现,让人惊奇。你也可能需要重新设计你的测试以规避那些存在问题的界面控件。
第三个原因, GUI 设计方案的变动会直接带来 GUI 自动化测试复杂度的提高。在开发的整个过程中,图形界面经常被修改或者完全重设计,这是出了名的事情。一般来讲,第一个版本的图形界面都是很糟糕。如果处在图形界面方案不停变动的时候,就开展 GUI 自动化测试是不会有任何进展的,你只能花费大量的时间修改测试脚本,以适应图形界面的变更。不管怎样,即便界面的修改会导致测试修改脚本,你也不应该反对开发人员改进图形界面。一旦原始的设计完成后,图形界面接口下面的编程接口就固定下来了。
上面提到的这些原因都是基于采用 GUI 自动化测试的方法完成产品的功能测试。图形界面接口当然需要测试,可以考虑实现 GUI 测试自动化。不过,你也应该考虑采用其他方法测试产品的核心功能,并且这些测试不会因为图形界面发生变化而被中断,这类测试应该采用命令行接口或者 API 接口。我曾经看到有人选择 GUI 自动化测试,因为,他们不打算修改被测试产品,但是,最终他们认识到必须对产品做修改,以保证 GUI 测试自动化可以正常工作。无论你选择哪种方法,自动化都需要对被测试的产品做修改。因此,采用可编程的接口是最可靠的。
为了让 API 接口测试更为容易,应该把接口与某种解释程序,例如 Tcl 、 Perl 或者 Python 绑定在一起。这使交互式测试成为可能,并且可以缩短自动化测试的开发周期。采用 API 接口的方式,还可以实现独立的产品模块的单元测试自动化。
一个关于隐藏可编程接口的例子是关于 InstallShield—— 非常流行的制作安装盘的工具。 InstallShield 有命令行选项,采用这种选项可以实现非 GUI 方式的安装盘,采用这种方式,从提前创建好的文件中读取安装选项。这种方式可能比采用 GUI 的安装方式更简单更可靠。
另一个例子是关于如何避免基于 WEB 软件的 GUI 自动化测试。采用 GUI 测试工具可以通过浏览器操作 WEB 界面。 WEB 浏览器是通过 HTTP 协议与 WEB 服务器交互的,所以直接测试 HTTP 协议更为简单。 Perl 可以直接连接 TCP/IP 端口,完成这类的自动化测试。采用高级接口技术,譬如客户端 JAVA 或者 ActiveX 不可能利用这种方法。但是,如果在合适的环境中采用这种方式,你将发现这种方式的自动化测试比 GUI 自动化测试更加便宜更加简单。
我曾经受雇在一家公司负责某个产品 GUI 相关的自动化测试,该产品也提供命令行接口,不过,他们已经实现了 GUI 的自动化测试。经过一段时间的研究,我发现找到图形界面中的 BUG 并不困难,不过,用户并不关注图形界面,他们更喜欢使用命令行。我还发现我们还没有针对最新的产品功能(这些功能即可通过 GUI 的方式,也可以通过命令行的方式使用)实现自动化测试。我决定推迟 GUI 自动化测试,扩展命令行测试套,测试新增的产品功能。现在回过头看这个决定,我没有选择 GUI 自动化测试是最大的成功之处,如果采用了 GUI 自动化测试所有的时间和努力都会浪费在其中。他们已经准备好做 GUI 自动化测试了,并且已经购买了一套测试工具和其他需要的东西,但我知道在开展具体的 GUI 自动化测试活动中,会遇到各种各样的困难和障碍。
无论你需要支持图形界面接口、命令行接口还是 API 接口,如果你尽可能早的在产品设计阶段提出产品的可测试性设计需求,未来的测试工作中,你很可能成功。尽可能早的启动自动化测试项目,提出可测试性需求,会使您走向自动化测试成功之路。
步骤五:具有可延续性的设计
在开篇的故事中,我们看到由于自动化工程师把注意力仅仅集中在如何使自动化运转起来,导致测试自动化达不到预期的效果。自动化测试是一个长期的过程,为了与产品新版本的功能和其他相关修改保持一致,自动化测试需要不停的维护和扩充。自动化测试设计中考虑自动化在未来的可扩充性是很关键的,不过,自动化测试的完整性也是很重要的。如果自动化测试程序报告测试用例执行通过,测试人员应该相信得到的结果,测试执行的实际结果也应该是通过了。其实,有很多存在问题的测试用例表面上执行通过了,实际上却执行失败了,并且没有记录任何错误日志,这就是失败的自动化。这种失败的自动化会给整个项目带来灾难性的后果,而当测试人员构建的测试自动化采用了很糟糕的设计方案或者由于后来的修改引入了错误,都会导致这种失败的测试自动化。失败的自动化通常是由于没有关注自动化测试的性能或者没有充分的自动化设计导致的。
性能:提高代码的性能往往增加了代码的复杂性,因此,会威胁到代码的可靠性。很少有人关心如何对自动化本身加以测试。通过我对测试套性能的分析,很多测试套都是花费大量的时间等候产品的运行。因此,在不提高产品运行性能的前提下,无法更有效的提高自动化测试执行效率。我怀疑测试自动化工程师只是从计算机课程了解到应该关注软件的性能,而并没有实际的操作经验。如果测试套的性能问题无法改变,那么应该考虑提高硬件的性能;测试套中经常会出现冗余,也可以考虑取出测试套中的冗余或者减少一个测试套中完成的测试任务,都是很好的办法。
便于分析:测试自动化执行失败后应该分析失败的结果,这是一个棘手的问题。分析执行失败的自动化测试结果是件困难的事情,需要从多方面着手,测试上报的告警信息是真的还是假的?是不是因为测试套中存在缺陷导致测试执行失败?是不是在搭建测试环境中出现了错误导致测试执行失败?是不是产品中确实存在缺陷导致测试执行失败?有几个方法可以帮助测试执行失败的结果分析,某些方法可以找到问题所在。通过在测试执行之前检查常见的测试环境搭建问题,从而提高测试套的可靠性;通过改进错误输出报告,从而提高测试自动化的错误输出的可分析性;此外,还可以改进自动化测试框架中存在的问题。训练测试人员如何分析测试执行失败结果。甚至可以找到那些不可靠的、冗余的或者功能比较独立的测试,然后安全地将之删除。上面这些都是减少自动化测试误报告警、提高测试可分析性的积极有效的方法。另外,有一种错误的测试结果分析方法,那就是采用测试结果后处理程序对测试结果自动分析和过滤,尽管也可以采用这种测试结果分析方法,不过这种方法会使自动化测试系统复杂化,更重要的是,后处理程序中的 BUG 会严重损害自动化测试的完整性。如果由于自动化测试本身存在的缺陷误把产品中的正常功能视为异常,那该怎么办?我曾经看到测试小组花费开发测试自动化两倍的时间来修改测试脚本,并且不愿意开展培训过程。那些仅仅关注很浅层次测试技术的测试管理者对这种方法很感兴趣,他们排斥采用隐藏测试复杂度的方法。
综上所述,应该集中精力关注可以延续使用的测试套,从以下几方面考虑,测试的可检视性、测试的可维护性、测试的完整性、测试的独立性、测试的可重复性。
可读性: 很多情况下,在测试人员开始测试项目之前,公司已经有了一套测试脚本,并且已经存在很多年了。我们可以称之为 “ 聪明的橡树 ”(wise oak tree)[Bach 1996] 。大家很依赖它,但是并不知道它是什么。由于 “ 聪明的橡树 ” 类型的测试脚本缺乏可读性,在具体应用中,那些脚本常常没有多大的实用价值,越来越让人迷惑。因此,测试人员很难确定他们实际在测试什么,反而会导致测试人员对自身的测试能力有过高的估计。测试人员能够检视测试脚本,并且理解测试脚本究竟测试了什么,这是很关键的。好的文档是解决问题的手段之一,对测试脚本全面分析是另外一个手段。由上面两种方法可以引申出其它的相关方法,我曾经在一个项目中使用过引申之后的方法。在测试脚本中插桩,把所有执行的产品相关的命令记录到日志里。这样,当分析日志确定执行了哪些产品命令,命令采用了何种参数配置时,可以提供一个非常好的测试记录,里面记录了自动化测试执行了什么,没有执行什么。如果测试脚本可读性不好,很容易变得过分依赖并没有完全理解的测试脚本,很容易认为测试脚本实际上做的工作比你想象中的还要多。测试套的可读性提高后,可以更容易的开展同行评审活动。
可维护性:在工作中,我曾经使用过一个测试套,它把所有的程序输出保存到文件中。然后,通过对比输出文件内容和一个已有的输出文件内容的差别,可以称已有的输出文件为 “ 标准文件 ” ( “gold file” )。在回归测试中,用这个方法查找 BUG 是不是明智之举。这种方法太过于敏感了,它会产生很多错误的警告。随着时间的推移,软件开发人员会根据需要修改产品的很多输出信息,这会导致很多自动化测试失败。很明显,为了保证自动化测试的顺利进行,应该在对 “ 标准文件 ” 仔细分析的基础上,根据开发人员修改的产品输出信息对之做相应的修改。比较好的可维护性方法是,每次只检查选定的产品的某些特定输出,而不是对比所有的结果输出。产品的接口变动也会导致原来的测试无法执行或者执行失败。对于 GUI 测试,这是一个更大的挑战。研究由于产品接口变化引起的相关测试修改,并研究使测试修改量最小的方法,测试中采用库是解决问题的方法。当产品发生变化的时候,只需要修改相关的库,保证测试与产品的变动同步修改即可。
完整性:当自动化测试执行后,报告测试执行通过,可以断定这是真的吗?这就是我称之为测试套的完整性。在前面的故事中,当没有对自动化测试完整性给予应有的关注的时候,发生了富有喜剧性的情况。我们应该在多大程度上相信自动化化测试执行结果?自动化测试执行中的误报告警是很大的问题。测试人员特别讨厌由于测试脚本自身的问题或者是测试环境的问题导致测试执行失败,但是,对于自动化测试误报告警的情况,大家往往无能为力。你期望自己设计的测试对 BUG 很敏感、有效,当测试发现异常的时候,能够报告测试执行失败。有的测试框架支持对特殊测试结果的分类方法,分类包括 PASS , FAIL 和第三种测试结果 NOTRUN 或者 UNRESOLVED 。无论你怎么称呼第三种测试结果,它很好的说明了由于某些测试失败导致其他测试用例无法执行而并非执行失败的情况。得到正确的测试结果是自动化测试完整性定义的一部分,另一部分是能够确认执行成功的测试确确实实已经执行过了。我曾经在一个测试队列中发现一个 BUG ,这个 BUG 引起测试队列中部分测试用例被跳过,没有执行。当测试队列运行完毕后,没有上报任何错误,我不得不通过走读代码的方式发现了这个 BUG 。如果,我没有关注到这个 BUG ,那么可能在认识到自动化测试已经出现问题之前,还在长时间运行部分测试用例。
独立性:采用自动化方法不可能达到和手工测试同样的效果。当写手工测试执行的规程时候,通常假定测试执行将会由一个有头脑、善于思考、具有观察力的测试人员完成的。如果采用自动化,测试执行是由一台不会说话的计算机完成的,你必须告诉计算机什么样的情况下测试执行是失败的,并且需要告诉计算机如何恢复测试场景才能保证测试套可以顺利执行。自动化测试可以作为测试套的一部分或者作为独立的测试执行。测试都需要建立自己所需要的测试执行环境,因此,保证测试执行的独立性是唯一的好方法。手工回归测试通常都相关的指导文档,以便一个接着一个有序地完成测试执行,每个测试执行可以利用前一个测试执行创建的对象或数据记录。手工测试人员可以清楚地把握整个测试过程。在自动化测试中采用上述方法是经常犯的错误,这个错误源于 “ 多米诺骨牌 ” 测试套,当一个测试执行失败,会导致后续一系列测试失败。更糟糕的是,所有的测试关联紧密,无法独立的运行。并且,这使得在自动化测试中分析合法的执行失败结果也困难重重。当出现这种情况后,人们首先开始怀疑自动化测试的价值。自动化测试的独立性要求在自动化测试中增加重复和冗余设计。具有独立性的测试对发现的缺陷的分析有很好的支持。以这种方式设计自动化测试好像是一种低效率的方式,不过,重要的是在不牺牲测试的可靠性的前提下保证测试的独立性,如果测试可以在无需人看守情况下运行,那么测试的执行效率就不是大问题了。
可重复性:自动化测试有时能够发现问题,有时候又无法发现问题,对这种情况实在没有什么好的的处理办法。因此,需要保证每次测试执行的时候,测试是以同样的方式工作。这意味着不要采用随机数据,在通用语言库中构造的随机数据经常隐藏初始化过程,使用这些数据会导致测试每次都以不同的方式执行,这样,对测试执行的失败结果分析是很让人沮丧的。这里有两个使用随机数据发生器的的方法可以避免上述情况。一种方法是使用常量初始化随机数据发生器。如果你打算生成不同种类的测试,需要在可预测,并且可控制的情况下建立不同类型的随机数据发生器。另外一个办法是提前在文件中或数据库中建立生成随机测试数据,然后在测试过程中使用这些数据。这样做看起来似乎很好,但是我却曾经看到过太多违反规则的做法。下面我来解释到底看到了什么。当手动执行测试的时候,往往匆匆忙忙整理文件名和测试数据记录。当对这些测试采用自动化测试方法,该做哪些工作呢?办法之一是,可以为测试中使用的数据记录给固定的命名。如果这些数据记录在测试完成后还要继续使用,那么就需要制定命名规则,避免在不同的测试中命名冲突,采用命名规则是一种很好的方法。然而,我曾经看到有些测试只是随机的命名数据记录,很不幸,事实证明采用这种随机命名的方式不可避免的导致命名冲突,并且影响测试的可重复性。很显然,自动化工程师低估了命名冲突的可能性。下面的情况我遇到过两次,测试数据记录的名字中包含四个随机产生的数字,经过简单的推算如果我们采用这种命名方式的时候,如果测试使用了 46 条记录,会存在 10% 冲突的可能性,如果使用 118 条记录,冲突的几率会达到 50% 。我认为测试当中使用这种随机命名是出于偷懒的想法 —— 避免再次测试之前写代码清除老的数据记录,这样引入了问题,损害了测试的可靠性和测试的完整性。
测试库:自动化测试的一个通用策略是开发可以在不同测试中应用的测试函数库。我曾经看到过很多测试函数库,自己也写了一些。当要求测试不受被测试产品接口变动影响的时候,采用测试库方法是非常有效的。不过,根据我的观察测试库已经使用的太多了,已经被滥用了,并且测试库往往设计的不好,没有相关的文档支撑,因此,使用测试库的测试往往很难开展。当发现问题的时候,往往不知道是测试库自身的问题,还是测试库的使用问题。由于测试库往往很复杂,即便在发现测试库存在问题,相关的维护人员也很不愿意去修改问题。通过前文中的论述,可以得出结论,在一开始就应该保证测试库设计良好。但是,实际情况是测试自动化往往没有花费更多的精力去保证一个优良设计的测试库。我曾经看到有些测试库中的功能根本不再使用了或仅仅使用一次。这与极限编程原则保持一致,即 ” 你将不需要它 ” 。这会导致在测试用例之间的代码出现一些重复,我发现微小的变化可能仍然存在,很难与测试库功能协调。你可能打算对测试用例作修改,采用源代码的方式比采用库的方式更容易修改。如果有几个测试,他们有某些共同的操作,我使用剪切和粘贴的方式去复制代码,有的人认为我采用的方法不可理喻。这允许我根据需要修改通用代码,我不必一开始尝试和猜测如何重用代码。我认为我的测试是很容易读懂的,因为阅读者不必关心任何测试库的语法。这种办法的优势是很容易理解测试,并且很方便扩展测试套。在开发软件测试项目的时候,大多数程序员找到与他们打算实现功能类似的源代码,并对源代码做修改,而不是从头开始写代码。同样,在写测试套的过程中可以采用上述方法,这也是代码开发方式所鼓励的方法。我比较喜欢写一些规模比较小的测试库,这些库可以被反复的使用。测试库的开发需要在概念阶段充分定义,并且文档化,从始至终都应该保持。我会对测试库作充分的测试后,才在测试中使用这些测试库。采用测试库是对所有面临的情况作权衡的。千万不要打算写一个大而全的测试库,不要希望有朝一日测试人员会利用你的测试库完成大量的测试,这一天恐怕永远不会到来。
数据驱动测试: 把测试数据写入到简单表格中,这种测试技术得到了越来越广泛的应用,这种方法被称为表驱动( table-driven ),数据驱动 (data-driven) 或者 “ 第三代 ” 自动化测试( “third generation” automation )。这需要写一个解析器,用来解释表格中的数据,并执行测试。该测试架构的最主要的好处是,它允许把测试内容写在具有一定格式的表格中,这样方便数据设计和数据的检视。如果测试组中有缺少编程经验的业务专家参与测试,采用数据驱动测试方法是很合适的。数据驱动测试的解析器主要是由测试库和上层的少量开发语言写成的代码组成的,所以,上面关于测试库的说明放在这里是同样合适的。在针对上面提到的少量代码的设计、开发、测试的工作,还存在各种困难。代码所采用的编程语言是不断发展的。也许,测试人员认为他们需要把第一部分测试的输出作为第二部分测试的输入,这样,加入了新的变量。接下来,也许有人需要让测试中的某个环节运行一百次,这样加入一个循环。你可以采用其他语言,不过,如果你预料到会面临上述情况的时候,那么做好采用一些能够通过公开的渠道获取的编程语言,比如 Perl,Python 或者 TCL ,这样比设计你自己的语言要快的多。
启发式确认:我曾经看到很多测试自动化没有真正意义上的结果校验,其原因有两个,一个原因是做完全意义上的自动化测试结果确认从技术上讲是很困难的,另外一个原因是通过测试设计规格很难找出自动化测试的预期结果。这很不幸。不过,采用手工校验测试结果的方法是真正意义上的测试校验。标准文件( Gold file )是另外一中校验测试结果的方法。首先,捕获被测试程序的输出,并检视程序的输出,然后,把输出信息文档化,并归档,作为标准文件。以后,自动化测试结果与标准文件作比较,从而达到结果校验的目的。采用标准文件的方法,也有弊端。当产品发生变化,自动化测试的环境配置发生变化,产品的输出发生变化的时候,采用标准文方法,会上报大量的误报告警。做好的测试结果校验方法是,对输出结果的特定内容作分析,并作合理的比较。有时候,很难知道正确的输出结果是什么样的,但是你应该知道错误的输出结果是什么样的。开展启发式的结果校验是很有帮助的。我猜想一些人在自动化测试中设计了大而全的测试结果校验方法,是因为担心如果结果校验漏掉了任何信息,可能导致自动化测试自身出现错误。不过,我们在测试过程中往往采用折衷的做法,没有采用大而全的测试结果校验方法,这样就不得不面对少量漏测情况的出现的风险。自动化测试不能改变这种情况的出现。如果自动化工程师不习惯采用这种折衷的方法,那么他必须找相关人员咨询,寻找一种合适的测试结果校验策略,这需要有很大的创造性。目前有很多技术可以保证在不产生误报告警的情况下,找到被测试产品的缺陷。
把注意力放在通过设计保证测试的可延续性上,选择一个合适的测试体系架构,你将进一步迈向成功的自动化测试。
步骤六:有计划的部署
在前面的故事中,当自动化工程师没有提供打包后的自动化测试程序给测试执行人员,会影响到测试执行,测试执行人员不得不反过来求助自动化工程师指出如何使用自动化测试程序。
作为自动化工程师,你知道如何利用自动化方法执行测试和分析执行失败的结果。不过,测试执行人员却未必知道如何使用自动化测试。因此,需要提供自动化测试程序的安装文档和使用文档,保证自动化测试程序容易安装和配置。当安装的环境与安装的要求不匹配,出现安装错误的时候,能够给出有价值的提示信息,便于定位安装问题。
能够把自动化测试程序和测试套作为产品对待,那真是太好了。你应该对自动化测试程序和测试套开展测试,保证它们不依赖于任何专用的库或者是设备上的任何其他程序。
保证其他测试人员能够随时利用已经提供的自动化测试程序和测试套开展测试工作;保证自动化测试是符合一般测试执行人员的思维习惯的;保证测试执行人员能够理解测试结果,并能够正确分析失败的测试执行结果;这需要自动化工程师提供自动动化测试相关的指导性文档和培训。
作为测试管理者,你希望在自动化工程师离开前,能够识别并修改测试套中的所有问题。自动化工程师迟早会离开的,如果你没有及时的把测试套中的问题提出来,就会面临废弃已有的测试套的决定。
良好的测试套有多方面的用处。良好的测试套支持对产品新版本的测试;良好的测试套在新的软件平台上可以很方便的验证产品的功能;良好的测试套支持每天晚上开始的软件每日构造过程;甚至开发人员在代码 check in 之前,用良好的测试套验证代码的正确性。
测试套的共享也很重要。很难预见以后什么人会继续使用你开发的测试套。因此,尽量让产品开发测试团队中的成员都很容易获得你的测试套。可以把测试套放在公司的内部网络上,这是个很好的办法。这样,大家就不必为了获取一份需要的测试套而四处打听。有些人总是感觉自己的测试套还没有最终完工或者不够完美,而没有拿出来与人分享,这种做法一定要改变,共享出来的测试套不一定非常完美,共享才是关键。
有计划的自动化测试部署,保证你的测试套能够被产品相关人员获取到,你就向成功的自动化测试又迈进了一步。并且你的自动化测试会被一次又一次的重用。
步骤七:面对成功的挑战
当你完成了所有的事情,测试套已经文档化了,并且文档已经交付了。测试执行人员能够理解要开展的测试,并知道如何完成测试执行。随着你所负责产品的进一步开发和维护,测试被反复重用。虽然,在自动化使测试变简单的同时,也总是使测试过程复杂化。测试人员需要学习如何诊断自动化测试执行失败的情况,如果不这样做,测试执行人员会认为执行失败的情况是由自动化引起,然后,自动化工程师被叫过来帮助诊断每一个执行失败的情况,开发人员往往也会认为执行失败是由于自动化测试自身引起的问题,这样,测试执行人员就不得不学习通过手工的方式,或者通过采用少量脚本的方式重现自动化测试发现的问题,以证明他们确实发现了产品当中的 BUG 。
测试套的相关工作还没有结束,为了提高测试覆盖率或者测试新的产品特性,需要增加更多的测试。如果已有的测试不能正常工作,那么需要对之修改;如果已有的测试是冗余的,那么需要删除这部分测试。
随着时间的推移,开发人员也会研究你设计的测试,改进产品的设计并且通过模拟你的测试过程对产品做初步测试,研究如何使产品在第一次测试就通过,这样,你设计的测试很可能无法继续发现新的问题,这种现象被称为一种杀虫剂悖论。这时候,会有人对你的测试有效性提出质疑,那么,你必须考虑是否应该挖掘更严格的测试,以便能够发现开发人员优化之后的产品中的缺陷。
以前,我提到过一个基本上无法实现的设想,设想通过按下一个按钮就完成了所有的测试工作。自动化测试是不是全能的,手工测试是永远无法完全替代的。
有些测试受测试环境的影响很大,往往需要采用人工方法获取测试结果,分析测试结果。因此,很难在预先知道设计的测试用例有多大的重用性。自动化测试还需要考虑成本问题,因此,千万不要陷入到一切测试都采用自动化方法的错误观念中。
我曾经主张保证给与测试自动化持续不断的投入。但是,在开展自动化测试的时候,一个问题摆在面前,测试自动化应该及时的提供给测试执行人员,这个不成问题,但是如何保证需求变更后,能够及时提供更新后的自动化测试就是个大问题了。如果自动化测试与需求变更无法同步,那么自动化测试的效果就无法保证了,测试人员就不愿意花费时间学习如何使用新的测试工具和如何诊断测试工具上报的错误。识别项目计划中的软件发布日期,然后把这个日期作为里程碑,并计划达到这个里程碑。当达到这个里程碑后,自动化工程师应该做什么呢?如果自动化工程师关注当前产品版本的发布,他需要为测试执行人员提供帮助和咨询,但是,一旦测试执行人员知道如何使用自动化测试,自动化测试工程师可以考虑下一个版本的测试自动化工作,包括改进测试工具和相关的库。当开发人员开始设计产品下一个版本中的新特性的时候,如果考虑了自动化测试需求,那么自动化测试师的设计工作就很好开展了,采用这种方法,自动化测试工程师可以保持与开发周期同步,而不是与测试周期同步。如果不采用这种方式,在产品版本升级的过程中,自动化测试无法得到进一步的改进。
持续在在自动化投入,你会面临成功的挑战,当自动化测试成为测试过程可靠的基础后,自动化测试的道路将会越来越平坦。
参考文献:
Bach, James. 1996. “Test Automation Snake Oil.” Windows Technical Journal , (October): 40-44. http://www.satisfice.com/articles/test_automation_snake_oil.pdf
Dustin, Elfriede. 1999. “Lessons in Test Automation.” Software Testing and Quality Engineering (September): 16-22.
http://www.stickyminds.com/sitewide.asp?ObjectId=1802&ObjectType=ART&Function=edetail
Fewster, Mark and Dorothy Graham. 1999. Software Test Automation , Addison-Wesley.
Groder, Chip. “Building Maintainable GUI Tests” in [Fewster 1999].
Kit, Edward. 1999. “Integrated, Effective Test Design and Automation.” Software Development (February). http://www.sdmagazine.com/articles/1999/9902/9902b/9902b.htm
Hancock, Jim. 1997 “When to Automate Testing.” Testers Network (June).
http://www.data-dimensions.com/Testers’Network/jimauto1.htm
Hendrickson, Elisabeth. 1999. “Making the Right Choice: The Features you Need in a GUI Test Automation Tool.” Software Testing and Quality Engineering Magazine (May): 21-25. http://www.qualitytree.com/feature/mtrc.pdf
Hoffman, Douglas. 1999. “Heuristic Test Oracles: The Balance Between Exhaustive Comparison and No Comparison at All.” Software Testing and Quality Engineering Magazine (March): 29-32.
Kaner, Cem. 1997. “Improving the Maintainability of Automated Test Suites.” Presented at Quality Week. http://www.kaner.com/lawst1.htm
Linz , Tilo and Matthias Daigl. 1998. “How to Automate Testing of Graphical User Interfaces.” European Systems and Software Initiative Project No. 24306 (June). http://www.imbus.de/html/GUI/AQUIS-full_paper-1.3.html
Jeffries, Ronald E., 1997, “XPractices,”
http://www.XProgramming.com/Practices/xpractices.htm
Marick, Brian. 1998. “When Should a Test Be Automated?” Presented at Quality Week. http://www.testing.com/writings/automate.pdf
Marick, Brian. 1997. “Classic Testing Mistakes.” Presented at STAR. http://www.testing.com/writings/classic/mistakes.html
Pettichord, Bret. 1996. “Success with Test Automation.” Presented at Quality Week (May). http://www.io.com/~wazmo/succpap.htm
Thomson, Jim. “A Test Automation Journey” in [Fewster 1999]
Weinberg, Ge

自动化运维工具puppet安装配置

2017年2月21日 评论已被关闭

自动化运维工具puppet安装配置
http://blog.csdn.net/linuxlsq/article/details/50838189
1. 准备工作

两台机器:
192.168.1.100(服务端)
192.168.1.101 (客户端)
两台机器关闭selinux,清空iptables规则,并保存,设置hostname

100上
hostname master.aming.com
编辑/etc/sysconfig/network 定义hostname

101上
hostname client.aming.com
编辑/etc/sysconfig/network 定义hostname
重启服务器

编辑hosts文件
100和101全部为
192.168.1.100 master.aming.com
192.168.1.101 client.aming.com
安装ntpdate,并建立自动同步时间的任务计划:
yum install -y ntp
crontab -e //加入
*/10 * * * * ntpdate time.windows.com
2. 服务端安装

安装puppet 源
rpm -ivh http://yum.puppetlabs.com/el/6/products/x86_64/puppetlabs-release-6-7.noarch.rpm

安装服务端程序
yum install -y puppet-server
启动服务
service puppetmaster start

开机启动
chkconfig puppetmaster on

3. 客户端安装

安装puppet 源
rpm -ivh http://yum.puppetlabs.com/el/6/products/x86_64/puppetlabs-release-6-7.noarch.rpm

安装客户端程序
yum install -y puppet

修改配置文件
vi /etc/puppet/puppet.conf
在最后面添加:
listen = true
server = master.aming.com
runinterval = 30 //主动更新,每隔30s

然后启动puppet服务
/etc/init.d/puppet start

手动生成ssl证书
puppet agent –test –server master.aming.com

4. 服务端查看,签发客户端的证书

puppet cert list –all
会看到client.aming.com 的key,正常应该会在行首有一个+,如果没有说明还没有签发

签发客户端
puppet cert –sign client.aming.com

5. 测试

服务端上
vi /etc/puppet/manifests/site.pp
加入如下内容:
node default {
file {
“/tmp/123.txt”: content => “test,test”;
}
}
客户端上
puppet agent –test –server master.aming.com
这样会在客户端上生成一个 /tmp/123.txt的文件,并且内容为 testtest
6. 配置自动签发证书

服务端上删除客户端证书
puppet cert clean client.aming.com

客户端上删除ssl下的文件
rm -rf /var/lib/puppet/ssl/*

服务端更改配置文件
vim /etc/puppet/puppet.conf在[main]下面加一行
autosign = true
服务端创建自动签发的配置文件
vim /etc/puppet/autosign.conf
加入如下内容:
*.aming.com

重启puppetmaster服务
/etc/init.d/puppetmaster restart

客户端重启puppet服务
/etc/init.d/puppet restart

这样就能在服务端上自动签发证书了。当然不重启服务,手动连一下服务端也可以
客户端执行:
puppet agent –test –server master.aming.com

扩展: puppet更新方式 http://www.cnphp6.com/archives/66975

7. 模块管理

首先要理解几个概念,模块、类、资源。 模块是puppet的最大单元,模块里面有类,类下面有资源。 puppet管理的文件、用户、服务、任务计划等全部由这些单元组成。

下面我们来定义一个模块:
在服务端上做如下操作:
mkdir /etc/puppet/modules/testm //模块名字就是testm
cd !$
mkdir {files,manifests,templates} //一个模块下需要有这三个目录,files存一些文件(可以为空),manifests存配置文件,templates存模板(可以留空)
touch manifests/init.pp //这个是必须的
vi manifests/init.pp //内容如下
class testm{
file {“/tmp/2.txt”:
owner => “root”,
group => “root”,
mode => 0400,
source => “puppet://$puppetserver/modules/testm/1.txt”
}
}

说明:类名字也叫做testm, 类下面定义了一个资源file,文件名字叫做/tmp/2.txt ,owner,group,mode定义文件的属主、数组以及权限,source定义这个文件从哪里获取。 $puppetserver一会也要定义一下,这里指的是puppet server服务器上/etc/puppet/modules/testm/files/1.txt

下面要继续定义一个很关键的配置文件:
vim /etc/puppet/manifests/site.pp //内容如下
$puppetserver = ‘master.aming.com’

node ‘client.aming.com'{
include testm
}
说明:$puppetserver 定义服务端的主机名,node后面为客户端的主机名,这里面定义该客户端要加载的模块
配置完成后,在客户端执行命令:
puppet agent –test –server=master.aming.com //如果客户端上启动了puppet服务,不用执行这命令,它也会自动同步的
上面的模块其实只是同步了一个文件而已,那么要想同步一个目录如何做?我们可以通过实现同步一个目录来做一个包发布系统。 比如在一台机器上编译安装好了apache,那么就可以通过这样的模块把这个apache目录整个分发到其他机器上。

模块配置文件如下:
class apache{
file {“/usr/local/apache2”:
owner => “root”,
group => “root”,
source => “puppet://$puppetserver/modules/apache/apache2”,
recurse => true,
purge => true

}
}
其中recurse=>true 这个参数很关键,它表示递归的意思,没有这个不能同步目录。purge参数可以保证当服务端删除某个文件,客户端可以跟着删除。

远程执行命令:
exec {“123”:
unless => “test -f /tmp/aminglinux.txt”,
path => [“/bin”, “/sbin”, “/usr/bin”, “/usr/sbin”],
command => “/bin/touch /tmp/aminglinux.txt”
}
说明:unless后面的命令作为一个条件,当条件成立时,不会执行下面的命令,如果想要条件成立时,执行下面的命令,用 onlyif。要注意的是,我们一定要给执行的这条命令加个条件,使用unless就可以,必须满足这个条件才能执行命令,否则这个命令会一直执行,不太妥当。
cron资源:
cron {“aming1”:
command => “/sbin/ntpdate time.windows.com”,
user => “root”,
minute => “*/10”,
# ensure => “absent” //当增加了这行配置,则会把该cron删除掉
}

说明:分时日月周分别对应puppet里面的minute,hour,monthday,month,weekday
扩展学习 http://blog.chinaunix.net/uid-20639775-id-3314583.html

资源:

package http://puppet.wikidot.com/package
service http://puppet.wikidot.com/srv
exec http://puppet.wikidot.com/exec
cron http://puppet.wikidot.com/cron

常用 Git 命令清单

2017年2月16日 评论已被关闭

常用 Git 命令清单

一般来说,日常使用只要记住下图6个命令,就可以了。但是熟练使用,恐怕要记住60~100个命令。

下面是我整理的常用 Git 命令清单。几个专用名词的译名如下。

Workspace:工作区

Index / Stage:暂存区

Repository:仓库区(或本地仓库)

Remote:远程仓库

一、新建代码库

# 在当前目录新建一个Git代码库

$ git init

# 新建一个目录,将其初始化为Git代码库

$ git init [project-name]

# 下载一个项目和它的整个代码历史

$ git clone [url]

二、配置

Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。

# 显示当前的Git配置

$ git config –list

# 编辑Git配置文件

$ git config -e [–global]

# 设置提交代码时的用户信息

$ git config [–global] user.name “[name]”

$ git config [–global] user.email “[email address]”

三、增加/删除文件

# 添加指定文件到暂存区

$ git add [file1] [file2] …

# 添加指定目录到暂存区,包括子目录

$ git add [dir]

# 添加当前目录的所有文件到暂存区

$ git add .

# 添加每个变化前,都会要求确认

# 对于同一个文件的多处变化,可以实现分次提交

$ git add -p

# 删除工作区文件,并且将这次删除放入暂存区

$ git rm [file1] [file2] …

# 停止追踪指定文件,但该文件会保留在工作区

$ git rm –cached [file]

# 改名文件,并且将这个改名放入暂存区

$ git mv [file-original] [file-renamed]

四、代码提交

# 提交暂存区到仓库区

$ git commit -m [message]

# 提交暂存区的指定文件到仓库区

$ git commit [file1] [file2] … -m [message]

# 提交工作区自上次commit之后的变化,直接到仓库区

$ git commit -a

# 提交时显示所有diff信息

$ git commit -v

# 使用一次新的commit,替代上一次提交# 如果代码没有任何新变化,则用来改写上一次commit的提交信息

$ git commit –amend -m [message]

# 重做上一次commit,并包括指定文件的新变化

$ git commit –amend [file1] [file2] …

五、分支

# 列出所有本地分支

$ git branch

# 列出所有远程分支

$ git branch -r

# 列出所有本地分支和远程分支

$ git branch -a

# 新建一个分支,但依然停留在当前分支

$ git branch [branch-name]

# 新建一个分支,并切换到该分支

$ git checkout -b [branch]

# 新建一个分支,指向指定commit

$ git branch [branch] [commit]

# 新建一个分支,与指定的远程分支建立追踪关系

$ git branch –track [branch] [remote-branch]

# 切换到指定分支,并更新工作区

$ git checkout [branch-name]

# 切换到上一个分支

$ git checkout –

# 建立追踪关系,在现有分支与指定的远程分支之间

$ git branch –set-upstream [branch] [remote-branch]

# 合并指定分支到当前分支

$ git merge [branch]

# 选择一个commit,合并进当前分支

$ git cherry-pick [commit]

# 删除分支

$ git branch -d [branch-name]

# 删除远程分支

$ git push origin –delete [branch-name]

$ git branch -dr [remote/branch]

六、标签

# 列出所有tag

$ git tag

# 新建一个tag在当前commit

$ git tag [tag]

# 新建一个tag在指定commit

$ git tag [tag] [commit]

# 删除本地tag

$ git tag -d [tag]

# 删除远程tag

$ git push origin :refs/tags/[tagName]

# 查看tag信息

$ git show [tag]

# 提交指定tag

$ git push [remote] [tag]

# 提交所有tag

$ git push [remote] –tags

# 新建一个分支,指向某个tag

$ git checkout -b [branch] [tag]

七、查看信息

# 显示有变更的文件

$ git status

# 显示当前分支的版本历史

$ git log

# 显示commit历史,以及每次commit发生变更的文件

$ git log –stat

# 搜索提交历史,根据关键词

$ git log -S [keyword]

# 显示某个commit之后的所有变动,每个commit占据一行

$ git log [tag] HEAD –pretty=format:%s

# 显示某个commit之后的所有变动,其”提交说明”必须符合搜索条件

$ git log [tag] HEAD –grep feature

# 显示某个文件的版本历史,包括文件改名

$ git log –follow [file]$ git whatchanged [file]

# 显示指定文件相关的每一次diff

$ git log -p [file]

# 显示过去5次提交

$ git log -5 –pretty –oneline

# 显示所有提交过的用户,按提交次数排序

$ git shortlog -sn

# 显示指定文件是什么人在什么时间修改过

$ git blame [file]

# 显示暂存区和工作区的差异

$ git diff

# 显示暂存区和上一个commit的差异

$ git diff –cached [file]

# 显示工作区与当前分支最新commit之间的差异

$ git diff HEAD

# 显示两次提交之间的差异

$ git diff [first-branch]…[second-branch]

# 显示今天你写了多少行代码

$ git diff –shortstat “@{0 day ago}”

# 显示某次提交的元数据和内容变化

$ git show [commit]

# 显示某次提交发生变化的文件

$ git show –name-only [commit]

# 显示某次提交时,某个文件的内容

$ git show [commit]:[filename]

# 显示当前分支的最近几次提交

$ git reflog

八、远程同步

# 下载远程仓库的所有变动

$ git fetch [remote]

# 显示所有远程仓库

$ git remote -v

# 显示某个远程仓库的信息

$ git remote show [remote]

# 增加一个新的远程仓库,并命名

$ git remote add [shortname] [url]

# 取回远程仓库的变化,并与本地分支合并

$ git pull [remote] [branch]

# 上传本地指定分支到远程仓库

$ git push [remote] [branch]

# 强行推送当前分支到远程仓库,即使有冲突

$ git push [remote] –force

# 推送所有分支到远程仓库

$ git push [remote] –all

九、撤销

# 恢复暂存区的指定文件到工作区

$ git checkout [file]

# 恢复某个commit的指定文件到暂存区和工作区

$ git checkout [commit] [file]

# 恢复暂存区的所有文件到工作区

$ git checkout .

# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变

$ git reset [file]

# 重置暂存区与工作区,与上一次commit保持一致

$ git reset –hard

# 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变

$ git reset [commit]

# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致

$ git reset –hard [commit]

# 重置当前HEAD为指定commit,但保持暂存区和工作区不变

$ git reset –keep [commit]

# 新建一个commit,用来撤销指定commit# 后者的所有变化都将被前者抵消,并且应用到当前分支

$ git revert [commit]

# 暂时将未提交的变化移除,稍后再移入

$ git stash

$ git stash pop

十、其他

# 生成一个可供发布的压缩包

$ git archive

分类: Git版本管理工具 标签:

Nginx和LVS负载均衡的对比

2017年1月25日 评论已被关闭

Nginx和LVS负载均衡的对比
Nginx和LVS对比的总结:
Nginx工作在网络的7层,所以它可以针对http应用本身来做分流策略,比如针对域名、目录结构等,相比之下LVS并不具备这样的功能,所以Nginx单凭这点可利用的场合就远多于LVS了;但Nginx有用的这些功能使其可调整度要高于LVS,所以经常要去触碰触碰,触碰多了,人为出问题的几率也就会大。

Nginx对网络稳定性的依赖较小,理论上只要ping得通,网页访问正常,Nginx就能连得通,这是Nginx的一大优势!Nginx同时还能区分内外网,如果是同时拥有内外网的节点,就相当于单机拥有了备份线路;LVS就比较依赖于网络环境,目前来看服务器在同一网段内并且LVS使用direct方式分流,效果较能得到保证。另外注意,LVS需要向托管商至少申请多一个ip来做Visual IP,貌似是不能用本身的IP来做VIP的。要做好LVS管理员,确实得跟进学习很多有关网络通信方面的知识,就不再是一个HTTP那么简单了。

Nginx安装和配置比较简单,测试起来也很方便,因为它基本能把错误用日志打印出来。LVS的安装和配置、测试就要花比较长的时间了;LVS对网络依赖比较大,很多时候不能配置成功都是因为网络问题而不是配置问题,出了问题要解决也相应的会麻烦得多。

Nginx也同样能承受很高负载且稳定,但负载度和稳定度差LVS还有几个等级:Nginx处理所有流量所以受限于机器IO和配置;本身的bug也还是难以避免的。

Nginx可以检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点。目前LVS中 ldirectd也能支持针对服务器内部的情况来监控,但LVS的原理使其不能重发请求。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而恼火。

Nginx对请求的异步处理可以帮助节点服务器减轻负载,假如使用 apache直接对外服务,那么出现很多的窄带链接时apache服务器将会占用大 量内存而不能释放,使用多一个Nginx做apache代理的话,这些窄带链接会被Nginx挡住,apache上就不会堆积过多的请求,这样就减少了相当多的资源占用。这点使用squid也有相同的作用,即使squid本身配置为不缓存,对apache还是有很大帮助的。

Nginx能支持http、https和email(email的功能比较少用),LVS所支持的应用在这点上会比Nginx更多。在使用上,一般最前端所采取的策略应是LVS,也就是DNS的指向应为LVS均衡器,LVS的优点令它非常适合做这个任务。重要的ip地址,最好交由LVS托管,比如数据库的 ip、webservice服务器的ip等等,这些ip地址随着时间推移,使用面会越来越大,如果更换ip则故障会接踵而至。所以将这些重要ip交给 LVS托管是最为稳妥的,这样做的唯一缺点是需要的VIP数量会比较多。Nginx可作为LVS节点机器使用,一是可以利用Nginx的功能,二是可以利用Nginx的性能。当然这一层面也可以直接使用squid,squid的功能方面就比Nginx弱不少了,性能上也有所逊色于Nginx。Nginx也可作为中层代理使用,这一层面Nginx基本上无对手,唯一可以撼动Nginx的就只有lighttpd了,不过lighttpd目前还没有能做到 Nginx完全的功能,配置也不那么清晰易读。另外,中层代理的IP也是重要的,所以中层代理也拥有一个VIP和LVS是最完美的方案了。具体的应用还得具体分析,如果是比较小的网站(日PV小于1000万),用Nginx就完全可以了,如果机器也不少,可以用DNS轮询,LVS所耗费的机器还是比较多的;大型网站或者重要的服务,机器不发愁的时候,要多多考虑利用LVS。

成功实施DevOps的七个有力工具

2017年1月23日 评论已被关闭

成功实施DevOps的七个有力工具
http://www.toutiao.com/a6371156850456559873/
现如今,每个软件企业都在谈论DevOps,他们希望从DevOps中获得好处。DevOps本身不是开发工具,而是开发文化的一次革新,为了能够成功地实施DevOps,需要借助一些工具。Pavan Belagatti列出了7个强有力的工具可以帮助企业成功地实施DevOps。
1. Docker
Docker是容器市场的领头羊。随着越来越多的软件企业采用了微服务架构,容器化也成为一个大趋势。在接下来的几年,Docker会变得越来越流行。我们已经在生产环境使用Docker部署了很多服务。Docker简化了配置管理,提升了可操控性,并让横向扩展变得简单。Docker还能让容器在不同的位置自由地移动。
2. Git(GitHub)
Git是一个免费的开源分布式版本控制系统,不管是小型应用还是大型应,它都能应付自如。Git创建于10年前,因为当时的Linux社区需要这么一个可以支持分布式系统的SCM(Source Control Management)软件。这个平台有助于开发者们在上面进行协作。它的那些主要特性,比如代码仓库、代码拉取等等,对开发人员来说很有吸引力。与GitHub的集成十分容易,几乎任何系统都可以连接到GitHub上,没有什么特殊限制。GitHub还可以作为一个网络社交平台,你可以在上面放置你的个人信息和项目相关的数据。GitHub优于其它SCM工具的地方在于,它支持本地分支、过度区域和多工作流。
3. AWS
AWS为企业组织提供了灵活的服务,帮助企业高效地交付软件产品。相比敏捷,DevOps能够更快地交付产品,为了做到这一点,AWS为各个公司提供了强大的云计算服务。这些服务包括计算、存储、网络、数据库、数据分析、应用服务、部署、管理、移动、开发者工具以及IoT工具。
4.JIRA
JIRA是来自Altassian公司的一款很受欢迎的敏捷开发工具,它提供了众多功能,比如缺陷跟踪、问题跟踪,并在某种程度上为企业提供了项目管理功能。它还支持Scrum、看板、敏捷报告、组合计划、插件、移动应用,并提供了一组健壮的API。
5. Ansible
可以使用Ansible为DevOps打下牢固的根基。Ansible是一个简单但却十分强大的配置管理服务器,它帮助团队横向扩展IT自动化规模,管理复杂的部署,并提高生产力。它为团队乃至整个企业带来自动化。很多成功的公司都在使用Ansible来促进IT自动化,而且一旦用了Ansible就不会再考虑其它解决方案了。企业之所以喜欢Ansible,是因为它提供了一种完全不可变的服务器架构。不可变的服务器架构可以保证在添加、销毁或替换服务器时不会对服务造成任何影响。
6. Slack
Slack是一个集成工具,任何想实践敏捷和DevOps的组织都可以使用它。它容易监控,还支持通知机制,是一个简单且强大的工具。Slack通过创建通信通道来自动化执行常见的任务,并用它来分发实时信息,缩短团队间的反馈延迟,加快团队的行动,提升团队的生产力。
7. Shippable
Shippable可以帮助软件企业加快创新进程。它是一个流水线式的持续部署平台,一般被作为托管服务或企业服务器来帮助软件企业走向现代化。它让编码、打包、部署、运行Docker容器变得更容易。Shippable通过它的CI和CD平台来支持自动化。它在不破坏安全性的前提下使用顺畅的部署来自动化执行那些重复的、机械化的任务。

Docker与传统虚拟化的差别

2017年1月9日 评论已被关闭

Docker与传统虚拟化的差别
http://blog.csdn.net/u010022051/article/details/50952779
1. VM –> Dockers (职能更少)
原来由一个虚拟机变成现在多个Docker,每一个Docker里面所运行的服务智能会更少。
2. IP –> Ips (关系更加复杂)
一个IP变成多个IP,多个IP承载多个服务,整个应用之间的关系更加复杂,不像在原来有一个VM承载所有的服务 ,现在把所有的大的服务拆分为很多细小的微服务提供给用户,体现它的价值。
3. 服务节点增加
Docker扩容的机制很方便,服务节点会呈现一个明显上升的趋势,是一个曲线增长。
4. 生命周期更短
和传统的VM来比,Docker可能它的生命周期更短。

分类: Docker容器技术 标签:

安全防范:nginx下git引发的隐私泄露问题

2016年12月4日 评论已被关闭

安全防范:nginx下git引发的隐私泄露问题

http://www.cnblogs.com/beer/p/5589323.html
安全防范:nginx下git引发的隐私泄露问题
1 安全事件
最近阿里云服务器后台管理系统中收到一条安全提示消息,系统配置信息泄露:

http://my.domain.com/.git/config
能够被公网无认证即可访问,请修复。

一般情况下,配置信息泄露是相当严重的问题,往往会千万另外一个地方整片区域的 沦陷,比如:数据库。当然本例并没有这样,但是可以作为一个典型安全来进行讲解。

2 问题分析
由于目前的 web 项目的开发采用前后端完全分离的架构:前端全部使用静态文件,和后端代码完全分离,隶属两个不同的项目。表态文件使用 git 来进行同步发布到服务器,然后使用 nginx 指向到指定目录,以达到被公网访问的目的。

(pyvenv) ➜ web-app-front git:(master) ls -a
. .git .idea css fonts index.html tpl
.. .gitignore ReadMe.rst favicon.ico images js
将此项目发布到服务器的 /var/www/web-app-front 目录中,然后在Nginx中进行如下配置:

复制代码
# configuration of the server
server {
# the port your site will be served on
listen 80;
# the domain name it will serve for
server_name my.domain.com; # substitute your machine’s IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste

sendfile on;
keepalive_timeout 0;
location / {
alias /var/www/web-app-front/; # your webapp static
}

}
复制代码
以上配置,确实可以达到,只要访问 my.domain.com 的域,即可进入到 /var/www/web-app-front/ 目录,但是本目录下面有一些本来不想让外界访问到的文件也会被访问到,例如: .git 目录。

一般情况下,黑客可以通过常用的 路径 字典,轻松暴破到此路径及相应的文件。

3 可能危害
因为要使用持续集成系统,所以对于前端静态文件的发布也必须要使用自动化,使用自动化就必须避免交互式的密码输入。而git中避免使用交互式密码输入,主要有如下几种方法:

.netrc 保存明文账号和密码
在 url 中带明文账号和密码
使用 ssh-key 进行鉴权
当然,由于笔者使用的 ssh-key,所以并没有千万过多的隐私泄露,将危害控制到了最小(基本只泄露了这个仓库的名称信息,并没有危害)。

查看使用的 ssh-key 鉴权方式下的 .git/config 的内容:

复制代码
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote “origin”]
url = git@github.com:myteam/web-app-front.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch “master”]
remote = origin
merge = refs/heads/master
复制代码
但是,笔者不禁想起,以比较早期的时候,为了避免反复输入密码,曾经使用过在 url 中带明文账号和密码的方式来 clone 一个 git 仓库:

git clone https://username:password@github.com/myteam/web-app-front.git
即,把账号和密码放在url里面可以免去反复交互式输入账号密码的繁琐操作。这样的话 .git/config 就会包括如下内容了:

[remote “origin”]
url = https://username:password@github.com/myteam/web-app-front.git
显然,如上的疏忽就会导致如下内容被泄露:

账号名:username
密码:password
服务网站:github.com
项目组代号:myteam
项目仓库名称:web-app-front
然后黑客就可以轻松打开服务网站,使用指定的账号和密码登录。然后浏览开发人员所在组的所有代码,然后代码里面可能包含如下的内容:

数据库账号密码
服务器IP
服务器账号密码
其它隐私信息
将会完全被泄露出去,可以说,这样一个小疏忽会导致全线崩盘,这并不是耸人听闻。

4 处理方法
其实处理方法,最后仍然是这样一个思想:将权限最大化收拢,不过多外放任何不需要外放的权限。

由于本文是使用 nginx 来让外网具备访问文件目录的能力,所以此权限就在 nginx 层做配置,只需要将不需要被外界访问的目录进行排除设置即可。例如,不允许外部访问 .git 目录:

server {
location ~ /\.git {
deny all;
}
}
目录 .git 后是否带有”/”,带”/”只禁止访问目录,不带”/”禁止访问目录中的文件。

当然, nginx 还有更多的限制访问的配置,本文不再一一列举,读者有兴趣的可以查看其官网上的相关文档进行更细致的研究。

5 总结
对于服务器往往都放在公网云端的互联网从业人员来说,任何时候都不能对权限配置疏忽了,否则可能千万无法估量的损失。

git push错误;fatal: The remote end hung up unexpectedly

2016年12月4日 评论已被关闭

git push错误;fatal: The remote end hung up unexpectedly
http://blog.csdn.net/harry_helei/article/details/6997531

在ubuntu10.04终端上 执行以下命令:

[html] view plain copy
git clone git://XXX
XXX是源码路径,将git上的代码拷贝下来,然后分别执行:git commit和git push命令。执行git push之后,终端上直接输出一下错误:
[html] view plain copy
fatal: The remote end hung up unexpectedly
其它的没任何提示。
找google大神问了下,根据提示,大部分都是关于权限的问题,仔细检查了下,不存在这个问题。折腾了半天,后来经同事提醒,才知道原因是:Git clone git://xxx,这是一种只读方式来获取代码,无法进行git push。解决方法是用:git clone git@xxx,这是一种可以进行读和代码提交(git push)的方式获取源码,但需要进行密码确认。

GitHub push时提示“fatal: The remote end hung up unexpectedly”

2016年12月4日 评论已被关闭

GitHub push时提示“fatal: The remote end hung up unexpectedly”

http://www.cnblogs.com/Leon5/archive/2011/10/23/2222002.html

这几天在学习git的使用,顺便去网上找个了git代码仓库练练手。http://github.com

注册用户,建立项目什么的都很顺利。

然后网站提示如下:

首先,配置自己的git。

然后建立项目,添加文件,上传修改……

然后,喀……扯到蛋了。

上传时git提示:

Agent admitted failure to sign using the key. Permission denied (publickey)

fatal: The remote end hung up unexpectedly

查看github的官方文档

#1. Check for SSH keys.
$ cd ~/.ssh
#2. Backup and remove existing SSH keys.
$ lsLists all the subdirectories in the current directory
$ mkdir key_backupmakes a subdirectory called "key_backup" in the current directory
$ cp id_rsa* key_backupCopies the contents of the id_rsa directory into key_backup
$ rm id_rsa*
#3. Generate a new SSH key.
$ ssh-keygen -t rsa -C "your_email@youremail.com"
#4. Add your SSH key to GitHub.
#5. Test everything out.
$ ssh -T git@github.com

大概意思就是你现在本地建立自己的SSH密码对,然后将公钥上传到github就行了。

额,好复杂……按照提示折腾了一下,果然可以了。

分类: Git版本管理工具 标签:

docker无法用exec进入容器的问题[cannot allocate memory]

2016年12月4日 评论已被关闭

docker无法用exec进入容器的问题[cannot allocate memory]
http://xiaorui.cc/2015/06/11/docker无法用exec进入容器的问题cannot-allocate-memory/
今同事小飞飞遇到一个坑爹的问题,可乐死我了…. 我发现他们组docker用的量也不少,但是经常出问题…. 这次是无法使用docker -it exec 进入容器。奇怪的是docker的提示是 内存无法分配,我们ps aux看了下docker的后端进程,内存已经用到40G了… … 

[ruifengyun@wx-social-web01 socialx]$ docker exec -it wh-online-deploy bash
Cannot run exec command 7559431b2205817b2405d33cc22339dcf90f9e3a9f8c01b2f93e7562bcf1f279 in container c326f588d91bf77a3234ac0a063543e8b27d69f43934b486593f2a1c2dd33f61: fork/exec /usr/bin/docker: cannot allocate memory Error starting exec command in container

docker的版本是1.5

[ruifengyun@wx-social-web01 socialx]$ docker -v
Docker version 1.5.0, build a8a31ef/1.5.0

[ruifengyun@wx-social-web01 socialx]$ free -m

total used free shared buffers cached
Mem: 64375 48876 15499 0 505 9739
-/+ buffers/cache: 38631 25744
Swap: 0 0 0

看了下docker的github里的issue,大多数人把overcommit_memory配置成1或者2 .

[ruifengyun@wx-social-web01 socialx]$ cat /proc/sys/vm/overcommit_memory
0
[ruifengyun@wx-social-web01 socialx]$ cat /proc/sys/vm/overcommit_ratio
50

您还可以配置交换空间;在这种情况下,进程不会被杀死,但如果内存使用量增长太多,系统可能会变得反应迟钝。
这虽然在一定程度上保证不死,但是问题是docker为毛占用了40G的内存… 最后的解决方法是,万能重启….

关于 docker cannot allocate memory Error starting exec command in container 的继续探讨…..

7-13,有遇到这jb问题了….. 已经确定其中一个容器里面的应用有个模块有内存泄漏的问题,fix解决….

但是让人奇怪的是,从docker主机外面查看内存占用,不会看到具体的进程,只会看到docker进程占用了50g的内存….

分类: Docker容器技术 标签:

关于git上传文件过大报错的问题 remote: warning: Large files detected.

2016年12月4日 评论已被关闭

关于git上传文件过大报错的问题 remote: warning: Large files detected.
http://blog.csdn.net/memray/article/details/43154779
今天往git上传了个项目,没有注意有个500m的大家伙在里面,就一并commit+push了,然后噩梦就来了。
首先是报错:

remote: warning: Large files detected.
# remote: warning: File big_file is 55.00 MB; this is larger than GitHub’s recommended maximum file size of 50 MB

一看不就是文件过大报错了嘛,直接文件delete重新commit,没想到问题继续。。
然后又尝试重试新建一个小的同名文件继续commit,问题继续。。

后来找到github上的一个帮助页面 Working with large files,照着”Removing the local file added with the most recent unpushed commit”的步骤操作了一番,最终未遂。但我的问题应该是下面的关于“Removing the file added in an older commit”才能解决的(因为我已经提交并push了),可是教程里只写了通过git-filter-branch解决,但是命令不能用~

想到我的问题一定是这个大文件已经保存到了log中,因此无论我怎么删改,这个文件没有从log中剔除就总会报出相同的错误,最后又是在万能的StackOverflow上有人给出了解决方法,命令如下:

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
git filter-branch -f –index-filter “git rm -rf –cached –ignore-unmatch FOLDERNAME” — –all
把你的文件或者文件夹位置替换掉那个FOLDERNAME就可以了,T_T 我再也不乱放大文件了。

分类: Git版本管理工具 标签:

fatal: the remote end hung up unexpectedly

2016年12月4日 评论已被关闭

fatal: the remote end hung up unexpectedly
http://blog.sina.com.cn/s/blog_71d4414d0100wfwq.html
发生在push命令中,有可能是push的文件过大导致
解决方法:
windows:
在 .git/config 文件中加入
[http]
postBuffer = 524288000

linux:
git config http.postBuffer 524288000

gitlab使用过程中遇到大文件上传或下载失败的问题,总结一下

2016年12月4日 评论已被关闭

gitlab使用过程中遇到大文件上传或下载失败的问题,总结一下
https://my.oschina.net/sayonala/blog/294197
摘要: 平时代码使用gitlab维护,为了方便使用http方式进行代码的上传及下载,遇到文件过大上传失败提示httpcode 411和413的问题,还有就是比较大的二进制文件下载提示httpcode 502的问题,特将解决方法进行记录,以备参考。
环境如下:gitlab服务器redhat,客户端环境mac os,如果是其他环境遇到问题仅供参考

如果gitlab上传代码提示:

error: RPC failed; result=22, HTTP code = 411

该问题是由于客户端设置的http_post_buffer大小不足导致的,解决方法如下:

进入到工程所在的终端目录下执行:

git config http.postBuffer 524288000

如果gitlab上传代码提示:

error: RPC failed; result=22, HTTP code = 413

该问题是由于gitlab服务器端client_max_body_size参数过小大致的,解决方法如下:

进入到服务器的终端目录:/etc/nginx下,编辑nginx.conf,在http配置段中增加如下配置

client_max_body_size 500m #大小自行调节

如果gitlab clone代码提示:

error: RPC failed; result=22, HTTP code = 502

该问题一般都是由于gitlab服务器端上的文件过大,导致客户端下载文件超时,gitlab使用unicorn进行webserver管理,如果客户端下载文件超过30s,unicorn就会结束该线程,因此这里的解决方案就是设置unicorn的超时时间,方法如下:

进入到gitlab服务器的终端目录:/home/git/gitlab/config/下,编辑unicorn.rb
# nuke workers after 30 seconds instead of 60 seconds (the default)
timeout 120
调整该项时间值,即可调整超时时间,具体设置自行调节

分类: Git版本管理工具 标签:

Default Problem with zabbix mysql install

2016年11月25日 评论已被关闭

Default Problem with zabbix mysql install

https://www.zabbix.com/forum/showthread.php?t=44965

I try to install ZABBIX with tut: https://www.zabbix.com/documentation…_from_packages
But in this step:

PHP Code:
# apt-get install zabbix-server-mysql zabbix-frontend-php

I get error:

PHP Code:
The following packages have unmet dependencies:
zabbix-server-mysql : Depends: libsnmp15 (>= 5.4.3~dfsg) but it is not installable
E: Unable to correct problems, you have held broken packages.

Then, i install libsnmp15, but it shows:

PHP Code:
Package libsnmp15 is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
However the following packages replace it:
libsnmp30:i386 libsnmp30 libsnmp-base
E: Package ‘libsnmp15’ has no installation candidate

I use ubuntu 13.10, and already installed libsnmp30, Zabbix require libsnmp15.

Any solutions for me?

 

 

 

Try installing this:
Code:
sudo apt-get install libsnmp-dev
then run again
Code:
# apt-get install zabbix-server-mysql zabbix-frontend-php
and see if it helps.

I wonder what is causing this issue. I could successfully accomplish this task yesterday on my virtual Ubuntu 13.10 desktop.

Is your Ubuntu up to date?

Code:
sudo apt-get update && sudo apt-get upgrade

 

 

 

wget http://repo.zabbix.com/zabbix/3.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_3.0-1+xenial_all.deb

dpkg -i zabbix-release_3.0-1+xenial_all.deb

 

分类: Linux监控管理 标签:

【git】fatal: This operation must be run in a work tree

2016年11月22日 评论已被关闭

【git】fatal: This operation must be run in a work tree
【git】fatal: This operation must be run in a work tree
2014-03-16 20:49 9877人阅读 评论(0) 收藏 举报
分类: linux菜鸟手记(185)
版权声明:本文为博主原创文章,未经博主允许不得转载。
之前是这么弄的 http://blog.csdn.net/commshare/article/details/20526369 ,感觉思路还是不太清晰。

今天新建立一个工程,需要一个仓库。
用Git –bare init创建的empty的仓库,不能git add,

会会报错fatal: This operation must be run in a work tree 。

但是,据说用git init的可以。
http://blog.csdn.net/commshare/article/details/21337313

解决办法有几个,
参考 http://blog.sina.com.cn/s/blog_630bf12f0100nl7i.html
参考 http://stackoverflow.com/questions/1456923/why-am-i-getting-the-message-fatal-this-operation-must-be-run-in-a-work-tree

===============

我选用的是:

仓库用git –bare init,

而我的实际的工程目录下用git init,git remote add origin ,git add 某个文件,git commit ,git push之后,

远程的仓库就ok了。

用gitweb也可以顺利的看到。

之前是这么弄的 http://blog.csdn.net/commshare/article/details/20526369 ,感觉思路还是不太清晰。

今天新建立一个工程,需要一个仓库。
用Git –bare init创建的empty的仓库,不能git add,

会会报错fatal: This operation must be run in a work tree 。

但是,据说用git init的可以。
http://blog.csdn.net/commshare/article/details/21337313

解决办法有几个,
参考 http://blog.sina.com.cn/s/blog_630bf12f0100nl7i.html
参考 http://stackoverflow.com/questions/1456923/why-am-i-getting-the-message-fatal-this-operation-must-be-run-in-a-work-tree

===============

我选用的是:

仓库用git –bare init,

而我的实际的工程目录下用git init,git remote add origin ,git add 某个文件,git commit ,git push之后,

远程的仓库就ok了。

用gitweb也可以顺利的看到。

分类: Git版本管理工具 标签:

error: src refspec master does not match any. 错误处理办法

2016年11月21日 评论已被关闭

error: src refspec master does not match any. 错误处理办法

http://www.cnblogs.com/jeremylee/p/5715289.html
本地仓库使用如下命令初始化:

$ git init
之后使用如下命令添加远程库:

$ git remote add origin git@github.com:hahah/ftpmanage.git
然后使用

$ git push -u origin master
出现如下错误:

error: src refspec master does not match any.
error: failed to push some refs to ‘git@github.com:hahaha/ftpmanage.git’
原因:

本地仓库为空

解决方法:使用如下命令 添加文件;

$ git add add.php addok.php conn.php del.php edit.php editok.php ftpsql.sql index.php

$ git commit -m “init files”
之后在push过程中出现如下错误:

复制代码
$ git push -u origin master
Warning: Permanently added the RSA host key for IP address ‘xx.xx.xxx.xxx’ to the list of known hosts.
To git@github.com:hahaha/ftpmanage.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to ‘git@github.com:hahahah/ftpmanage.git’
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., ‘git pull …’) before pushing again.
hint: See the ‘Note about fast-forwards’ in ‘git push –help’ for details.
复制代码
提示使用 git pull 之后在 push

使用如下命令解决:

复制代码
$ git pull –rebase origin master
warning: no common commits
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:hahah/ftpmanage
* branch master -> FETCH_HEAD
* [new branch] master -> origin/master
First, rewinding head to replay your work on top of it…
Applying: init files
复制代码
继续push,成功。

复制代码
$ git push -u origin master
Counting objects: 10, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (10/10), done.
Writing objects: 100% (10/10), 5.15 KiB | 0 bytes/s, done.
Total 10 (delta 3), reused 0 (delta 0)
To git@github.com:hahaha/ftpmanage.git
a2b5c30..1044f15 master -> master
Branch master set up to track remote branch master from origin.
复制代码
大功告成!!!

分类: Git版本管理工具 标签:

keepalived+nginx双机热备笔记

2016年11月13日 评论已被关闭

keepalived+nginx双机热备笔记
http://imkerwin.com/588.html
os版本:CentOS release 6.8 (Final)

内核:2.6.32-642.1.1.el6.x86_64

keepalived版本:keepalived-1.2.22

keepalive安装:(当然为了省事也可以直接 yum install keepalived)

1.安装前先解决依赖问题。
yum -y install gcc gcc+ gcc-c++
yum install popt-devel openssl openssl-devel libssl-dev libnl-devel popt-devel

2.源码包安装。去官网把keepalived-1.2.22.tar下载到本地,解压,进入目录,./configure,make,make install

3.拷贝文件。(因个人安装目录会有区别,请留意绝对路径,和你本地保持一致)
cp /usr/local/sbin/keepalived /usr/sbin/
cp /usr/local/etc/rc.d/init.d/keepalived /etc/init.d/
cp /usr/local/etc/sysconfig/keepalived /etc/sysconfig/

4.启动&停止。
service keepalived start/stop /etc/init.d/keepalived start/stop

5.配置文件keepalived.conf说(理论上是指定/etc/keepalived/keepalived.conf这个,因为我启动的时候查看日志说启动这个)

=======================================================================

配置文件:

[root@lmsc-nginx1 ~]# cat /etc/keepalived/keepalived.conf
global_defs {
router_id LVS_DEVEL
}
#监测nginx进程状态,每2秒执行一次
vrrp_script chk_nginx {
script “/data/scripts/chk_nginx.sh” #检测脚本路径
interval 2
weight 2
}
vrrp_instance VI_1 {
state MASTER #从服务器为BACKUP
interface eth0 #绑定vip的网卡
virtual_router_id 51
priority 100 #从服务器要低于100
advert_int 1
mcast_src_ip XXXX.XXXX.XXXX.XXXX #MASTER服务器IP,从服务器写从服务器的IP
authentication {
auth_type PASS
auth_pass 111111
}
track_script {
chk_nginx #监测nginx进程状态
}
virtual_ipaddress {
XXXX.XXXX.XXXX.XXXX #虚拟IP 也就是vip
}
}

上面的配置适用于物理机,但是一般的云主机,对方会在路由上限制arp协议广播的那就需要改一下配置了,将mcast_src_ip XXXX.XXXX.XXXX.XXXX这段修改成下面(阿里云,金山云就需要如下配置)

unicast_src_ip XXXX.XXXX.XXXX.XXXX##(本地IP地址)

unicast_peer {

XXX.XXX.XXX.XXX##(对端IP地址)此地址一定不能忘记

}

====================================================================

检测脚本:chk_nginx.sh

#!/bin/bash
A=`ps -C nginx –no-header |wc -l`
if [ $A -eq 0 ];then
/data/nginx/sbin/nginx
sleep 3
if [ `ps -C nginx –no-header |wc -l` -eq 0 ];then
killall keepalived
fi
fi

重点配置的地方已经加了#号并且说明,主机和备机的配置文件差别也就服务器IP和priority的值不同,其他都一样,因此就不列出来了,另外还可以加上smtp的相关参数用于报警,这个我认为没有必要,因为我本地有zabbix。

6.keepalived日志 (/var/log/messages)。

7.测试成败,在主机杀掉keepalived进程,虚拟ip会自动漂移到备机。

8.遇到的问题,主和备都出现了绑定vip的情况,可以适用tcpdump vrrp命令看看是否有数据包进来,确定是否防火墙问题,主备之间vrrp包能否正常通讯,各自判定各自服务器已挂导致。解决方法,主备之间互相放行varrp iptables -A INPUT -i eth0 -p vrrp -s 主/备 -j ACCEPT

keepalived可以服务后,就剩下nginx的配置了,nginx的配置这里不多说了。

解决Jenkins 2.0 初始化界面卡住的问题

2016年11月5日 评论已被关闭

解决Jenkins 2.0 初始化界面卡住的问题

http://www.cnblogs.com/wzy5223/p/5277901.html

Jenkins 2.0 将要发布,但是试用alpha版本时,总是卡在初始化界面(设置插件的界面),如下图:

初始化

这个可以用浏览器的调试功能,将这个初始化界面删除,然后就可以继续执行到安装插件,重启以后初始化界面就不会出现了。但是在2016/03/13 以后更新的

jenkins 2.0用这个方法解决不了了,所以只能想其它办法。

这个界面是用来设置插件用的,jenkins在安装插件前总是尝试连接www.google.com,来判断网络是否连通。大家都知道谷歌的网站在大陆是连不上的,所以出现这个问题的原因很可能和这个有关。

 

开始验证猜测是否正确:

1.  下载最新的Jenkins2.0 http://mirrors.jenkins-ci.org/war-rc/2.0/jenkins.war

2.   java -jar jenkins.war

3.   cd $JENKINS_HOME/updates  ,我这里的路径等于  $HOME/.jenkins/updates      –$JENKINS_HOME的路径不同的安装方式都是不一样的

4.   vi default.json , 可以看到前面的键值对为: “connectionCheckUrl”:”http://www.google.com/” ,将其改为 “connectionCheckUrl”:”http://www.baidu.com/”

5.  访问 localhost:8080, 页面停在输入安全令牌的地方,输入安全令牌,然后继续。

6.   这时候可以看到选择插件的界面已经可以正常显示了。

 

让程序员变懒的工具 : Jenkins + 蒲公英

2016年11月5日 评论已被关闭

让程序员变懒的工具 : Jenkins + 蒲公英

http://www.cocoachina.com/ios/20150428/11698.html

关于懒惰

经常看到很多博文里面讲’懒惰’是一个优秀程序猿的良好品质,这一点我深以为然,因为在程序猿的工作中总是充满了重复劳动,也许正是因为这个原因,导致大部分程序猿慢慢变得懒惰,而那些没变懒的程序猿他们慢慢灭绝了~~~。而对于懒惰这个词,我们不能曲解它的意思,并不是怠倦、消沉的对待工作,而是当一个程序员遇到重复的工作时,懒惰的程序员首先想到的是我要开发出一个工具自动执行这些工作。

为什么需要工具

当 UI 妹子给你一大堆图片而没有给你加上 @2x 后缀时,看着妹子可怜的眼神,怎么忍心让妹子们返工,懒惰的程序员就在想了,这特么是一个循环重复的劳动,为啥不写个脚本自动给每张图片文件名加上一个 @2x 后缀呢,分分钟搞定,然后准时下班约会去了。。。。

所以很早之前我的第一个开源工具 dSYM 分析工具 就是这么来的,当我连在命令行中续修改了几个友盟统计后台收集到异常后,我发现这就是一个重复而且繁琐的劳动啊,所以我便花了两个多小时做了一个 APP 应用,这样以后我每次需要做的只是:1)打开应用,2)拖入 dSYM 文件 3)输入异常地址,便得到异常信息了。

而写这篇文章则讲述了我是如何一步一步从 1)手动打包 –> 2)Jenkins 打包,手动发布 –> 3)Jenkins 打包 + 蒲公英 分发 的。

起因

对于发包这个问题,相信是每个程序猿哥哥心中挥之不去的痛,而测试妹子们也在每次马上就发的承诺中得出一个结论 : “你是个大骗子”。

所以每次被测试妹子追着要测试包,产品经理说给我装一个开发中的新版本瞧瞧呗,后台哥哥说给我安装一个某某老版本的包调试一下啊。。。然后每次不得暂停下手中的工作,切换到某个版本,Archive。。。。终于有一次答应测试妹子吃饭前会给他们发包后,忙着忙着就忘掉直接去吃饭了,看着妹子 QQ 上发来各种鄙视的表情,这不是我想要的人生啊,我一定要改变在测试妹子心中的形象,所以自动化构建这件事情提上日程.

使用 Jenkins 半自动化

我直接选用了已经很成熟的 Jenkins 持续集成解决方案,至于如何配置就不做过多介绍了,网上有不少这类的文章。有了 Jenkins 后,给我带来最便利的一点就是,每次打包的时候,直接在公司的 Mac 服务器上进行操作,而我还可以继续进行手上的工作,打包完成后把 ipa 包发给测试,同时也教会了测试如何从 Jenkins 上下载已经打包好的 ipa 文件,就这样我可以随时在手机上打开公司内网的 Jenkins 打包,当我把这一切告诉测试妹子的时候,她用期望的眼神看着我说:“这是真的么。。。”

Jenkins + 蒲公英 升级

就这样用了一段时间,也没遇到什么问题,或许是比较爱折腾,我发现每次 Jenkins 打包好了之后,我还需要手动去下载,或者让测试他们下载,当测试拿到文件后,还需要将手机连到电脑用 iTunes 或者第三方工具安装文件,我想要是 Jenkins 打包完成后会自动通知测试更新并安装该多好,而且之前也听说过第三方的分发平台 “蒲公英”,于是我去蒲公英网站看了一番,很高兴的是他们开放上传 APP 和安装 APP 等 API,有了这个东西,我的想法便完全可以实现了:1)Jenkins 打包 2)打包成功后 IPA 文件上传到 Tomcat 服务器 3)通过 API 把 IPA 文件传给 蒲公英 4)上传成功后把安装地址通过邮件发送给测试。 5)测试直接在手机上打开地址安装。

流程图大概像这样:

图片

1.IPA 文件上传到 Tomcat 服务器

由于每次 Jenkins 打包的时候,编译后的文件是放在项目根目录下的 build 文件夹里面,每次 build 的时候这个文件夹内的文件都会被覆盖,所以每次 build 后我都会通过 FTP 把 IPA 文件上传到 Tomcat 上备份,同时还可以方便提供给别人下载,比如在给测试发送蒲公英的安装地址时,同时也可以给出 IPA 下载地址。

* 开启 Mac FTP-server

Mac 电脑本身是支持 FTP 服务的,只不过系统默认关闭了,Mountain Tweaks 这款软件可以很方便的修改系统的一些设置,比如是否开启打开 Window 动画,是否显示用户的 Library 文件夹,其中有一个选项就是是否开启系统的 FTP-server 功能。

图片

* 配置 Jenkins 的 FTP Server

Mac服务器支持 FTP-server 后,我在 Jenkins 上安装了 Publish Over FTP Plugin 这个插件,这个插件可以将指定的文件发送到选中的 FTP 服务器上去,安装完插件后,在 Jenkins 的系统设置中会多出一项 Publish over FTP 的设置,因为 Tomcat 和 Jenkins 是在一台电脑上,所以 Hostname 直接指向本地,Remote Directory 也直接指向 Tomcat 的 webapps 下对应 app 的目录。配置好后可以点 Test Configuration 测试一下,如果显示 success,则成功了。

图片

* 在 Job 的设置里面指定上传到 FTP 的文件

Jenkins 配置好 FTP Server 后,接下来就需要在 Job 中去设置打包成功后把哪些文件上传到指定的 FTP Server 中去了。在 增加构建后操作步骤中 有一个 Send build artifacts over FTP 选项,这里首先需要选择我们之前配好的 FTP Server。Source files 是我们构建目录下 build 文件夹内所有的文件,Remove prefix设置为 build 是告诉插件创建路径的时候不要包含 build,Remote directory则是我们指定的 FTP Server 上需要创建的目录,这里我以 Jenkins 构建的版本号去创建文件夹,之后取文件的时候,路径便会很方便拼接。

图片

2.通过 API 把 IPA 文件传给 蒲公英

打包成功了,并且文件也备份到 Tomcat 上去之后,接下来就需要编写脚本了,脚本需要的功能是:1)上传 IPA 文件到 蒲公英 2)发邮件通知测试。这两点通过脚本是很好实现的,已经放在 GitHub 上,如果想将脚本应用到自己的环境中,最主要的是如下这几行代码 :

图片

uKey、file_name、_api_key、installPassword这四个值是根据自己的情况配置的。project_name的值很重要,涉及到很多地方:1)tomcat 的 webapps 目录下面要有 project_name 对应的目录,因为在获取 ipa_file_tomcat_http_url 的时候,是需要 project_name的, 还有就是获取发给蒲公英的 IPA 文件时也需要知道 project_name

接着就需要让 Jenkins 去执行这个脚本了,通过对 Jenkins 插件的搜索,找到一个叫 Post-Build Script Plug-in 的插件,功能官方介绍写的很清楚:PostBuildScript makes it possible to execute a set of scripts at the end of the build.。

安装完这个插件后,在 Job 的 增加构建后操作步骤 中会多出一个 Execute a set of scripts 的选项,这里我只配置了 Build steps 中的 Execute shell,让它用 Python编译器去执行项目根目录下的脚本,还有就是 Execute script only if build success 勾选上:

图片

这样当 Jenkins 打包成功后,便会执行此脚本,最终达到了我的目的。

最终收到的邮件大概是这样的:

图片

如果是在手机上打开邮件的话,可以直接使用第三种方式:点我直接安装,这种方式最方便,其次是第二种,蒲公英在线安装,最后一种便是自己下载 IPA 包到本地,使用工具安装。

到这儿之前设想的都已经实现了,整个过程中从开发的角度来说,需要的只是点击一下 Jenkins 中的 立即构建 按钮,然后就继续做手头上的事情把!

总结

教科书上把会不会制造工具当做人和动物的根本区别,我觉得这也是判断一个好程序员的标准之一,优秀的程序员总是会去寻找好的工具,或者自己去创造一些工具来提高自己的生产效率,他们通过工具把那些浪费在重复劳动上的时间花在了更有意义的事情上去。

任何工具出现的最初目的都是为了提高生产效率,很庆幸在 iOS 开发的这个圈子中有一大批的先驱者,他们创造并开源了很多优秀的工具,为这个环境奠定了一个良好的基础,所以在工作或生活中,多创造工具,让自己变得更懒,却更有价值!

linux下jenkins + git 配置

2016年11月5日 评论已被关闭

linux下jenkins + git 配置
http://blog.sina.com.cn/s/blog_70481cb90102vj2d.html
1、插件安装
jenkins默认安装了CVS,Subversion,Maven和SSH。要使用Git进行版本控制,所以要在可选插件中选择安装Git plugin和GitHub plugin插件,安装之后重新启动就可以看到新的插件已经生效。

2、环境配置
进入”系统管理->系统设置”设置Jenkins的相关参数。主要是设置Git,在Git下的Path to executable一栏添加git的路径。如果想要使用邮件的功能,需要在邮件通知的一栏添加SMTP服务器和邮箱的相关信息,添加后点击Test的按钮测试一下能否正常发送邮件,这一功能可以在后面的项目中使Email Notification功能得以正常使用。

3、构建项目
点击”新Job”,输入”任务名称”,选择”构建一个自由风格的软件项目”,点击”OK”。系统自动进入”任务配置”界面。
4、配置构建方法

在”源码管理->Git”下的Repository URL输入Repository的Git地址(PS:可以选择分支)。

输入url后,添加私钥
在”构建触发器”中选择”Build when a change is pushed to GitHub “和”Poll SCM “,这两项的作用分别是当GitHub有版本库更新时触发Jenkins进行构建和定期检查版本库是否有更新,如果有更新则触发Jenkins进行构建。这里要注意Schedule语法,例如”*/2 * * * *”表示每隔2分钟检查一次。
点击保存,项目的配置就完成了,点击立即构建,Jenkin就会从github上将代码clone下来,然后自动编译项目,如果构建成功会是蓝色标记,如果构建失败会是红色标记。
构建完成后可以在项目中看到项目构建的具体信息,如工作区、变更集和每次构建的控制台输出等。这就是一个基本的基于Jenkins和Git的持续集成环境的搭建。