Monday, February 1, 2016

自动化测试简介

为什么要做自动化测试?

自动化测试可以做到人类无法做到的快速验证和反馈,从而提高软件质量和降低修复成本。
想象一下如果不写脚本去做压力测试,会是什么情形?

测试总类繁多,包括但不限于:

通过几十年的技术积累,上面所诉的90%都有相应的技术做自动化支持。由此可见业界对于测试自动化的推崇。


根据测试金字塔原理:


图:测试金字塔

金字塔越下层,说明运行速度越快,编写成本越低,应该在所有测试中占比最多。
金字塔越上层,说明运行速度越慢,编写成本越高,应该在所有测试中占比最少。

由此引出保障软件产品质量的三个基本测试:单元测试、集成测试和功能测试。

底层单元测试:

我们推荐的单元测试编写方法是TDD。通过TDD帮助我们理清需求,想清设计,从而编写更高质量的代码。你得到高覆盖率的单元测试仅仅是额外的奖励。
Java中我们用到的测试框架通常是JunitMockito
Scala我们会用Specs2

测试的编写应该从需求出发,每个测试都表达一个功能点,而不是从代码的角度去讨论单元测试,这点同时应该在方法名中体现。比如在猜数字的练习中,我们的测试描述应该写成 "should_tell_how_much_numbers_are_matched_when_I_guess",而不是"test_method_guess"。

另外为什么先写测试?
试着回答两个问题:先有需求还是先有代码?如何验证代码的正确性?
答案显而易见:先有需求,“实现了的需求”是检验代码正确性的唯一标准。
因此,我们应该根据需求编写相应的测试,并通过所有测试,以此来证明我们写的代码是可靠的。

具体写法,请参考示例

中间层集成测试:

在Restful应用中,集成测试通常是测试服务API。这种测试可以对某个服务进行端到端的测试,同时又避免了处理UI的复杂性。
API的测试,基于Java最常用的就是RestAssured,再加上Spring Test内存数据库等技术,使API测试能独立、可重复的运行。


上层功能测试:

功能测试也就是应用测试,是对产品整体的验证。功能测试只关心用户能接触到的内容,模拟用户使用产品,验证产品是否能解决用户问题,符合场景预期等。
最常见的就是UI测试,通过Selenium来模拟实际页面操作来验证产品功能。



所有测试都应遵照以下流程:

  1. 准备测试环境和被测对象
  2. 给定输入
  3. 验证输出

所有测试都应该符合以下标准:

  • 独立性:测试应能够清楚的表明一个功能或场景
  • 可重复性:测试应可重复运行,且都以同样的形式成功或失败
  • 自我验证:测试要无歧义的表达成功或失败
  • 完整性:测试应该不需要人为参与做类似于调整数据的操作

最后,要学会如何写自动化测试,重点是多练。可以从基础的题目开始练起,用自己擅长的语言。重点训练自己的测试思维,即我们是在验证用户价值,这样才能使测试真正有效。


Resources:
Kata练习题:http://codingdojo.org/

Books:
程序员的职业素养:http://book.douban.com/subject/11614538/

Wednesday, September 2, 2015

为什么应该在团队内完成整个开发生命周期

经常听到有人说,数据库很重要,所以应该有一个经验丰富的团队来把关。架构很重要,所以应该由一些架构师来统筹。

先不说这些高级团队到底能做到多大改善。但这种组织架构会带来致命的问题——组织的开发速度上限受限于这些高级团队,甚至是效率最低的那个。




如图,首先问题是,这些团队会在整个开发流程中成为瓶颈,我们无法通过横向扩展团队来提升组织的开发速度。这对软件产生价值的组织来说是致命的。

第二个问题是,开发中的沟通成本大量增加,团队间的沟通成本会远远大于团队内的沟通成本。如果功能开发团队依赖于大量其他团队,就会使整个开发成本变高,价值流速度降低。

第三个问题是,核心团队成员需要长时间培养,人员流动往往会造成致命的打击,就好像组织中有一根软肋,如果竞争花钱把某一个核心团队成员全部挖走,该组织可能会立刻消失。

由此可见,为了保持某些看起来很重要的东西(比如数据库,架构)运行良好,就让专业团队去做的想法有很多致命问题。

那怎么样才是好的实践呢?



特性团队 + 微服务

团队自己负责所有事务,从一开始就避免大型数据库和大型架构的设计,每个功能根据自己的需求,完成相应的服务设计、开发、测试、部署和上线。如果需要修改其他服务,也由该团队自己完成。通过自动化测试去保障质量,而不是由某个高级团队。

如果遇到遗留系统怎么办?

因为遗留系统可能没有足够的自动化测试去保障质量,所以首选的一定不是去修改它。把遗留系统API化,给遗留系统补测试,把一部分功能拆出来另外实现,都是我们常用的方法。
当然,我们还是避免不了去修改它,这种时候,修改还是由团队自己来完成,因为没有人能代替你去理解业务,没有人能代替你提供实现方案。只是团队需要自己足够谨慎,通过增加对遗留系统的了解以及找曾经在系统上工作过的人沟通,从而具备修改它的能力。



总之,指望把当前团队解决不了的问题扔给另一个团队去解决是不靠谱的,我们应该提升团队能力,使该团队具备解决问题的能力,而不是把希望寄托在别的团队上。

Thursday, July 16, 2015

Never register a domain on oray.com

Oray has a terrible service.

First, they require me to upload a photo within a personal ID by email and mention that the DNS would be affected if I don't upload the photo.

Second, I tried to transfer my domain out but there is on way to do that by myself. They don't provide the service in their web site. And they still require my to send a mail which include a hard copy of my personal ID and an additional paper form to their office. And they won't pay the fee of the mail.

Third, I made a phone call to their service centre. They told me the only way to transfer my domain out is to fill the additional paper form and send it to them with a hard copy of my ID. They had nothing to do.

Last thing is they never mentioned these above until I tried to transfer my domain out. Which means I was informed 5 years later after my first payment for my domain.

So at last, I try to get my auth-code through ICANN. The address of complaint page is below:

Hope this could help anyone who has the similar trouble with me.

Be away from these terrible registrars.


Wednesday, May 20, 2015

Surprise by the new html5 and css3 technologies

Recently I joined a course about how to do a UI design.

Here's the showcase.
https://heaton.github.io/week3/ (not available for IE and old Browsers)

These pages are all made by pure css 3 and html 5 with a little jQuery code for click events and touch events.



Friday, May 15, 2015

Git Tips

Shorten your Git commands - Alias

git config --global alias.[name] "command"

Examples

git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.cob "checkout -b"
git config --global alias.back "checkout master"
git config --global alias.cof "checkout --"
git config --global alias.pl "pull --rebase origin master"
git config --global alias.plf "!git stash && git pl && git stash pop" # ! means runing the command as shell command
git config --global alias.lo "log --graph --oneline"
git config --global alias.l "log --pretty=format:'%C(yellow)%h %C(red)%ad %C(green)%d %C(reset)%s [%C(blue)%an]' --date=short --graph"

A better git log tool - tig

TIG

install

brew install tig

Get commit from other branchs - cherry-pick

cherry-pick
git cherry-pick [CommitID]
git cherry-pick --no-commit [CommitID] # 把commit内容放到本地的cache里面
You can test cherry-pick on GitStudy.

Find commit which you force deleted - reflog

Git won’t really delete any commit even you use git reset --hard HEAD^. You can get it back by reflog.

Thursday, November 27, 2014

慢慢的,就没有了,就像从未存在过


几年以前,我曾经嘲笑过某科技界大佬。当时他说:也许90后、95后会慢慢不知道谷歌是什么网站。

那一年,这对于我来说简直就是世界上最好笑的笑话。谷歌,全世界最卓越的互联网公司,活在互联网的一代中国人,会不知道他们的网站?

今天,我收回这句嘲笑。因为这件不可能的事,它慢慢变成了现实。

没有人再关注什么谷歌不谷歌。对他们来说,百度也蛮好用的,反正他们几乎没用过谷歌。没有谷歌又怎样?大家还是开心的刷微博,看微信,听歌,看娱乐节目。对于从来就不知道谷歌的人来说,少了谷歌又有什么影响?



多年前,我们也是可以登陆Facebook的。其实这个网站和校内一样,也挺蠢的。可在上面你能看到老外们的生活,可以轻易的跟一万公里以外的人互相拜访,可以看到很多根本不会开到校内上的主页。你用汉语回复,下面给你聊起来的可能是香港仔,可能是台湾人。你用英语回复,说不定有比你英语用的更蹩脚的寂寞的北欧人来跟你搭讪。你感觉地球真的变成了地球村,你还没拉门走出去,别人就推门走了进来。

然后,它就没有了。起初,它的失踪激起了很大的声音,后来,声音就消失了。

多年前,我们也是可以登陆Twitter的。其实这个网站和微博一样,也不过是些信息流,刷上一整天,也不见得有什么用处。但至少,你可以以最快速度获取你想知道的任何新事,你会真正了解什么事情在全世界是流行的,而不是经过各种截图、翻译、转发,甚至曲解、断章取义、黑白颠倒的东西。你知道的是真相,赤裸裸的,也许有点太短的真相。但至少中间不会有无数人的加工与再加工,偏激、片面,就在这个过程中产生了,不管后来者有意还是无意。

然后,它就没有了。首先是它的本体没有了,然后它的模仿者也没有了,模仿者的模仿者也没有了。只剩一个模仿者的模仿者的模仿者,现在你每天能在上面看到无数广告。

多年前,我们也是可以登陆YouTube的。对于有的人来说,这个网站就是个大型优酷,当年有人信誓旦旦的说,没有YouTube,我们中国人会很快让优酷超过YouTube。可这么多年过去了,视频还是那么卡,内容还是那么垃圾,原创还是那么容易被盗窃,视频丰富度还是那么的可怜。在YouTube上,你能看到全世界最棒的手艺人,最逗乐的笑话,最天马行空的创意,最激荡人心的音乐,最美好的完美瞬间,可在优酷上,你想看一分钟视频,请先看半分钟广告。

哦,对了。Instagram,有些人可能感觉它和QQ空间也差不多。可我在上面关注了六百多个摄影师,它们都是顶好顶好的影像记录者,每天看他们的作品,我感觉到很幸福,那种即使没有到那里去,也身临其境的幸福。我还在上面认识了一个日本的爱自拍的帅小伙,一个爱喝酒的韩国大叔,一个十年前到过中国今天会在每张我发的紫禁城照片下点赞的美国大爷,一个美丽无比的俄罗斯妹子,我和他们基本上都难以交流,语言是很大的障碍,但几个简单的单词,心意也就到了,这种感觉,有时候比多年老友相聚还兴奋。因为这是人类不同族群自由交流互相沟通的过程,这种过程很神奇,真的很神奇。

可现在,它没有了,它之所以没有就因为在某个特定的时间你在搜索特定的词汇时,会搜出来特定的照片。虽然这么搜的人并不多,虽然看到的人也不会大惊小怪,也不会觉得天黑了,天亮了,天要塌了,天要变了。可它就是没了,Instagram,就这么没了。谷歌也是这么没的,Twitter也是这么没的,Facebook也是这么没的。不知道是什么人,在什么场合,说了什么话,下了什么决定。就要有超过十亿人像陷于哥谭市的孤岛里一样,看着一座又一座桥梁被炸掉,又被炸掉,又被炸掉,然后,就什么都没了。

我时常觉得悲哀,真的好悲哀,一个我根本不认识也不知道是谁的人,也许是一个群体,在不断抢走我身边的东西,而我却无能为力。我抱怨一声,他听不到,任何人都听不到。我怒吼一句,身边的大多数人却像看疯子一样的看着我。我哀嚎一声,这声音被阻碍在黑黑的幕墙以里。我发出尖锐的嘶吼,这声音传不了多远,就和我那被抢走的东西一样,消失了,不见了,就像从来没存在过一样。

对于本来就没存在过的东西,有谁又会觉得在意呢?那些本来拥有又被掠夺的人的哀愁,后来的人又怎么懂呢?我曾经是拥有一切的,我曾经是拥有世界的,我站在这片土地上,呼吸的是自由的空气,饮下的是自由的琼浆玉液。就在长的无法计数的时间里,我自由生命的一部分又一部分就这么被杀死了,突然就杀死了。可我还始终觉得,它们还奄奄一息的活着,就像它们是慢慢的死去的一样。

可它们终归是死了,而且随着它们的死,愈来愈多的事情慢慢的发生了,很慢很慢,几乎不被人察觉,可还是发生了。

没有谷歌,我可以用百度呀。可某些结果被越挪越后,越挪越后,最后就不见了。就像本来就不该搜出这个结果一样。

没有Facebook,我可以用校内呀。可你想发只有在Facebook上能发的文章,很快在校内上就失踪了。接着,校内变成了人人,话题变成了人人都关心的话题。大家都在抢着看星座、明星、八卦、娱乐。没有人会关心什么消失了,反正它们本来也没多少存在感。

没有YouTube,我可以用优酷呀。可你却经常只能在优酷上看到抄袭别人的作品,而且还不署名,而且还洋洋得意,而且还自我陶醉,就好像那个idea本来属于他自己一样。你看了还要惊呼,他是如此的有创意!好一个抄袭的创意,可你却不知道,因为你不知道这个世界上有个网站叫YouTube。

没有Twitter,我还可以用微博呀。可你想知道最近发生了什么,你搜的越勤快,越能看到越明显的??“根据相关法律法规,相关搜索结果不予显示??”。时间长了,你想,反正知道了也没什么用,不如不看了。

慢慢的,一扇又一扇的门关上了。今天你打开世界上最大的博客网站,发现它没了。明天你一看,世界上最好的设计师分享网站没了,一开始是刷新的很慢很慢,后来它就没了。过两天再一看,平常每天都会读两篇文章的媒体网站没了,那里的文章缤纷多彩,最后都变成了该页无法显示几个字。再过几个月,大学的网站不让上了,摄影师的网站不让上了,就连百度日本这种自家网站,也没了。

接着,漫画看不了了,接着,动画看不成了。接着,美剧英剧失踪了。下载美剧英剧的网站又又又又又失踪了。尊重正版,保护权益,行吧,然后字幕网站也没了。

游戏没了,你习惯性登陆的游戏网站,发现下载栏正在整治中。论坛关了,天天都在看的论坛,突然接到相关部门的电话,因为??“报备问题??”不让办了。个人网站,私人博客,对不起,说没就没有,你在上面存了多少多年辛勤耕耘的东西都没用。

你关注的人,有一天你登陆微博,发现他怎么好久都没说话了,然后你搜索了一下,发现他的账号不存在了,而且你搜他的名字,他的名字未予显示。

一盏一盏的灯,灭了。四面八方的光源,消失了。我们生活的五光十色的世界,变成了一片黑色。

天黑了,那么睡觉吧,但愿长醉不复醒,卧槽泥马勒戈壁。

最后,我们变成了一群做梦的人,这个梦的名字,叫根据相关法律法规,相关搜索结果不予显示梦。

作者:小海,来源:豆瓣网,原文已经被和谐

Thursday, March 27, 2014

Install Sonar on Ubuntu 12.04 with Postgresql

1. install JDK
sudo apt-get install default-jdk

2. Download the package on http://www.sonarqube.org/downloads/
unzip sonarqube-[version].zip

3. Change the config for Postgresql
vim sonar/conf/sonar.properties
change the username and password for progresql like this:
  sonar.jdbc.username=sonar
  sonar.jdbc.password=sonar
  sonar.jdbc.url=jdbc:postgresql://[ip:localhost if your db at same server]/sonar

4. If the jdk is installed, uncommet this line under in sonar/conf/wrapper.conf
wrapper.java.additional.6=-server

5. Set up for Postgresql Server:
sudo su postgres
createuser sonar -P
  enter password: sonar
  nnn

psql
  create database sonar with owner sonar encoding ‘utf8’;
  /q
6. If the Postgresql Server isn't on localhost, add a line for verification in pg_hba.conf
sudo vim /etc/postgresql/9.1/main/pg_hba.conf
  host    all             sonar     192.168.1.0/24             md5

7. Test to connect db server
sudo apt-get install postgresql-client
psql -d sonar -h [ip of db server] -U sonar

8. Start Sonar:
sudo sonar/bin/[linux-x86-64]/sonar.sh start

9. Register as a service:
sudo vim /etc/init.d/sonar
     #! /bin/sh
     /home/admin01/sonar4/bin/linux-x86-64/sonar.sh $*

sudo chmod 755 /etc/init.d/sonar
sudo update-rc.d sonar defaults
sudo service sonar start

10. maven config:
vim ~/.m2/setting.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
     <profiles>
          <profile>
               <id>sonar</id>
               <properties>
                    <sonar.jdbc.url>jdbc:postgresql://[ip]/sonar</sonar.jdbc.url>
                    <sonar.jdbc.username>sonar</sonar.jdbc.username>
                    <sonar.jdbc.password>sonar</sonar.jdbc.password>
                    <sonar.host.url>http://[ip]:9000</sonar.host.url>
               </properties>
          </profile>
     </profiles>
     <activeProfiles>
          <activeProfile>sonar</activeProfile>
     </activeProfiles>
</settings>

11. Push your project to Sonar
Add maven plugin:
            <plugin>
                <groupId>org.codehaus.sonar</groupId>
                <artifactId>sonar-maven-plugin</artifactId>
                <version>3.7.2</version>
            </plugin>


Run this:
mvn sonar:sonar