PHPDoc 介绍与安装

PHPDoc是一个用PHP写的强大的文档自动生成工具,对于有规范注释的php程序,能够快速生成具有结构清晰、相互参照、索引等功能的API文档。

PHPDoc的原理是: 扫描指定目录下面的php源代码,扫描其中的关键字,截取需要分析的注释,然后分析注释中的专用的tag,生成xml文件,接着根据已经分析完的类和模块的信息,建立相应的索引,生成xml文件对于生成的xml文件,使用定制的模板输出为html文件。

目前,PHPDoc的分析结果可以以HTML形式表现,由于使用了模板机制,可以很方便地定制风格。同时也提供了相应的接口,可以把API文档生成其他的形式,比如PDF,LATEX,WORD等。

以下是我的安装和使用过程。

增加php环境依赖

PHPDoc 依赖于 xsl 和 intl 插件,如果 php.ini 没有打开这两个插件的话要预先打开。当然也可以直接跳过,后边安装不了会弹出错误的,例如:

phpdocumentor/template-zend 1.3.2 requires ext-xsl * -> the requested PHP extension xsl is missing from your system.
zendframework/zend-i18n 2.1.6 requires ext-intl * -> the requested PHP extension intl is missing from your system.

找到你的 php.ini 文件,新增

extension=php_xsl.dll
extension=php_intl.dll

PHPDoc安装方式有三种

  1. PEAR
  2. PHAR
  3. Composer

composer方式尝试之后发现与其它插件依赖冲突,Can’t install with Composer - github issues,于是换用了 PEAR 方式。其他方式也可以参考官网

安装PEAR

下载文件 http://pear.php.net/go-pear.phar 放到 php 目录下。使用管理员权限下打开 cmd/powershell,执行

php go-pear.phar

一路回车即可。这个安装会询问几个问题,主要意思是

  • 以全局模式安装或者本地模式拷贝(应该是绿色安装不写入注册表的意思)
  • 确认安装目录
  • 确认修改 php.ini 文件

安装完成后提示注册环境变量。在安装目录下会生成 pear_env.reg 文件,双击即可。然后检查是否安装成功:

pear -h

最后注册pear的channel(不知道怎么翻译比较好了)

pear channel-discover pear.phpdoc.org

安装 PHPDoc

pear install phpdoc/phpdocumentor

于是就安装完成了。

PHPDoc的简单使用

最简单的命令是:

phpdoc -d [SOURCE_PATH] -t [TARGET_PATH]

-d  这个目录代表着需要生成文档的原始php文件目录(注意是目录) 
-t  这个目录代表着生成的文档存放目录

例如:

phpdoc -f baseTags.php -t docs

搭起服务器就可以访问了。或者直接本地打开index.html文件也可以查看。

要想获得更多参数说明, phpdoc -h即可。因为phpdoc可以使用模板,可以在官网上选择你中意的模板再导出。默认的样式如下图:

tips:phpdoc的中文文档真的很少,要深入使用还是尽量在官网上看。

小问题

  • GraphViz not installed

    在终端运行phpdoc时你可能会遇到如下问题(略过不解决也没问题的样子):

      Unable to find the `dot` command of the GraphViz package. Is GraphViz correctly installed and present in your path?
    

    这是由于系统没有安装 GraphViz 的原因。官网上下载GraphViz:http://www.graphviz.org/Download_windows.php 然后增加环境变量,例如我的是 C:\my_pp\Graphviz2.38\bin

  • Phpdoc No Summary found for this file

    在生成的文档页面中会有错误提示。其中有一个诡异的错误

      Type        Line    Description
      error       0       No summary was found for this file  
    

    具体的原因这个 Stackoverflow 回答的很好 —— 《Phpdoc No Summary found for this file》。以下是我的解决办法,在文件头部加上如下信息:

      /**
       * Class Category | Notification/NtCenter.php
       *
       * @package App\Notification\Models
       * @author kelvinblood <admin@kelu.org>
       * @version     v0.0.1 (2017-3-6)
       * @copyright   Copyright (c) 2017, kelu.org
       */
    

参考资料


laravel phpunit中使用namespace

原先项目并没有做单元测试。今天写了几个hello world,发现使用 namespace 时候报错

PHP Fatal error:  Class 'Tests\TestCase' not found in C:\Workspace\xxx\tests\Unit\ExampleTest.php on line 10

解决办法:

修改composer.json,增加如下设置:
   
"autoload-dev": {
   "psr-4": {
       "Tests\\": "tests"
   }

修改完成后 composer install 重新加载项目即可。

关于新增的autoload-dev的作用,以及composer.json文件的解释,下篇文章写一个。

参考资料


composer.json 配置文件说明

Java有Maven, Node.js有npm, ROR有gem,PHP有composer. 他们都是各个语言的包管理器。

下面将以一个composer.json为例,简单介绍Composer的使用方法。完整的文档可以查看最后的参考资料。

{
// ================================ 配置文件 ================================
    "name":             "kelu/app",
    "description":      "血衫非弧的app",
    "keywords":         ["kelvinblood", "kelu", "app"],
    "homepage":         "http://app.kelu.org ",
    "time":             "2016-12-30",
    "license":          "MIT",
    "authors": [{
        "name":         "Kelvin Blood",
        "email":        "xxx@xxx.org",
        "homepage":     "http://www.kelu.org",
        "role":         "CEO"
    }],
    "type": "project", // library project metapackage composer-plugin
    "repositories": [
        {
            "type": "vcs",
            "url": "https://git.oschina.net/apkj/phpwebframework.git"
        }
    ],
// ================================ 依赖管理 ================================
// === 默认情况下,composer只会获取稳定版本,修改后运行命令 composer install ===
    "require": {
        "php": ">=5.5.9",
        "laravel/framework": "5.1.*",
        "ignited/laravel-omnipay": "2.*",
        "lokielse/omnipay-alipay": "dev-master"
    },
// === 有些包依赖只会在开发过程中使用,正式发布的程序不需要这些包,这个时候,就需要用到另外一个键,即require-dev。例如,我们用phpunit单元测试,那么就可以通过require-dev引入这个开发环境下的依赖包
    "require-dev": {
        "fzaninotto/faker": "~1.4",
        "mockery/mockery": "0.9.*",
        "phpunit/phpunit": "~4.0",
        "phpspec/phpspec": "~2.1"
    },
    
// ================================ 自动加载 ================================
// === 加载文件最简单的方式就是require或者include, autoload,顾名思义,就是自动加载. 
// === 修改后,运行命令: composer dump-autoload, 让composer重建自动加载的信息
// === composer 提供了4种自动加载类型 classmap psr-0 psr-4 files 
// === files,对应的值是一个数组,数组元素是文件的路径,路径是相对于应用的根目录。
// === classmap,会在背后就会读取这个文件夹中所有的文件 然后再 vendor/composer/autoload_classmap.php 中怒将所有的 class 的 namespace + classname 生成成一个 key => value 的 php 数组.缺点是一旦增加了新文件,需要执行dump-autoload命令重新生成映射文件。
// === psr-0 现在这个标准已经过时
// === psr-4 支持将命名空间映射到路径。命名空间结尾的\\不可省略。当执行install或update时,加载信息会写入vendor/composer/autoload_psr4.php文件。如果希望解析指定路径下的所有命名空间,则将命名空间置为空串即可。
    "autoload": {
     "files":["lib/OrderManager.php"],
        "classmap": [
            "database"
        ],
         // FIG组织制定的一组PHP相关规范,简称PSR,其中PSR-0自动加载 PSR-1基本代码规范 PSR-2代码样式 PSR-3日志接口 PSR-4 自动加载
        "psr-4": {
            "App\\": "app/"         // 自动加载命名空间App,文件夹app里的文件
        }
    },
// 和require-dev类似,只在开发过程中自动加载
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests" // 自动加载Tests的命名空间
        }
    },
    
// ================================ 脚本 ================================
// === 在安装过程中的各个阶段挂接脚本。
    "scripts": {
        "post-install-cmd": [
            "php artisan clear-compiled",
            "php artisan optimize"
        ],
        "pre-update-cmd": [
            "php artisan clear-compiled"
        ],
        "post-update-cmd": [
            "php artisan clear-compiled",
            "php artisan optimize"
        ],
        "post-root-package-install": [
            "php -r \"copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "php artisan key:generate"
        ]
    },
    
// ================================ 设置 ================================
    "config": {
        "preferred-install": "dist", //Composer 的默认安装方法。 source、dist 或 auto
        "secure-http": false
    }
}

参考资料

参考资料


关于软件测试

最近在看关于软件测试方面的资料,整理了一些资料。文末列出了一些关于软件测试的观点,顺便推荐两个测试做的比较好的php项目。

何为软件测试

使用人工或自动的手段来运行或者测量软件系统的过程,以检验软件系统是否满足规定的要求,并找出与预期结果之间的差异。

软件测试应当遵循的原则

  • 测试显示缺陷的存在,但不能证明没有缺陷
  • 穷尽测试是不可能的,应设定及时终止的条件
  • 测试应尽早进行
  • 缺陷具备群集特性
  • 测试的杀虫剂悖论,不定期增删修改测试用例,从而发现软件缺陷
  • 测试的二八原则,80%的时间和资源用在20%的重点模块上
  • 测试活动依赖于测试背景,针对不同的测试背景,测试活动场景要求也是不一样的,比如对电信大并发量性能、金融的安全要求等.

软件测试的分类

按阶段划分

  1. 单元测试

    单元测试是对软件中的基本组成单位进行的测试。目的是检验软件基本组成单位的正确性。单元测试可以倒推要求开发人员正视需求,对自己的程序更有信心。

  2. 集成测试

    在单元测试的基础上,将所有软件单元按照概要设计规格说明的要求组装成模块、子系统或者系统的过程中各部分工作是否达到或实现相应技术指标以及要求的活动。偏于从技术角度进行测试实施方案

  3. 系统测试

    将各子系统结合起来,包括功能测试、非功能测试。非功能测试就包括很多了,性能测试、稳定性测试、可用性测试、安全测试等。注重整个系统完整的功能和性能,偏于从业务角度测试系统。

    • 功能测试:

       功能测试是对产品的各功能进行验证,以检查是否满足需求的要求。 其中又分为很多种:逻辑功能测试、界面测试、易用性测试、兼容性测试 一般功能测试使用的工具有:

      商用

      • QTP
      • WinRunner
      • silktest
      • rational robot 开源
      • selenium
      • watir
      • sikuli
    • 性能测试:

       性能测试是通过自动化测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。软件的性能包括很多方面,主要有时间性能和空间性能两种。 时间性能:主要是指软件的一个具体的响应时间。比如一个登录所需要的时间,一个交易所需要的时间等。当然,抛开具体的测试环境,来分析一次事务的响应时间是没有任何意义的。需要搭建一个具体且独立的测试环境。 空间性能:主要指软件运行时所消耗的系统资源,比如硬件资源,CPU、内存,网络带宽消耗等。 一般功能测试使用的工具有:

      • loadrunner
      • silkperformer
      • jmeter
      • webload
      • apache bench
      • loadui
    • 安全测试:

      安全测试检查系统对非法入侵的防范能力。这一类的工具有:

      • appscan web应用漏洞扫描
      • webinspect web应用漏洞扫描
      • nessus 服务器主机类漏洞扫描
      • nmap 端口嗅探
      • metasploit 渗透测试
      • webscarab 代理劫持分析
      • fortify 白盒测试工具,源代码静态分析
      • w3af Web应用程序攻击和检查框架
    • 兼容测试:

        兼容性测试主要是测试系统在不同的软硬件环境下是否能够正常的运行。

  4. 交付测试/验收测试

    • 功能确认测试
    • 安全可靠性测试
    • 易用性测试
    • 可扩充性测试
    • 兼容性测试
    • 资源占用率测试
    • 用户文档资料验收

按照对象可见度

黑盒测试、白盒测试、灰盒测试

按照状态

静态测试、动态测试

按照测试执行方法

  1. 手工测试

    手工测试就是由人去一个一个的去执行测试用例,通过键盘鼠标等输入一些参数,查看返回结果是否符合预期结果。

  2. 自动化测试

    自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。又可分为功能自动化测试与性能自动化测试。

冒烟测试、回归测试、随机测试

  这三种测试在软件功能测试过程中,既不算具体明确的测试阶段也不算是具体的测试方法。

  1. 冒烟测试

    是指在对一个新版本进行系统大规模的测试之前,先验证一下软件的基本功能是否实现,是否具备可测性。 引入到软件测试中,就是指测试小组在正规测试一个新版本之前,先投入较少的人力和时间验证一个软件 的主要功能,如果主要功能都没有实现,则打回开发组重新开发。这样做的好处是可以节省大量的时间成本和人力成本。

  2. 回归测试

    是指修改了旧代码后,重新时行测试以确认修改后没有引入新的错误或导致其他代码产生错误。 回归测试一般是在进行软件的第二轮测试开始的,验证第一轮中发现的问题是否得到修复。当然,回归也是一个循环的过程,如果回归的问题通不过,则需要开发人员修改后再次进行回归,直到通过为止。

  3. 随机测试

    是指测试中的所有输入数据都是随机生成的,其目的是模拟用户的真实操作,并发现一些边缘性的错误。 随机测试可以发现一些隐蔽的错误,但是也有很多缺点,比如测试不系统,无法统计代码覆盖率和需求覆盖率,发现的问题难以重现。一般是放在测试的最后执行。其实随机测试更专业的升级版叫 探索性测试

  4. 探索性测试

    探索性测试可以说是一种测试思维技术。它没有很多实际的测试方法、技术和工具。探索性强调测试人员的主观能动性,抛弃繁杂的测试计划和测试用例设计过程,强调在碰到问题时及时改变测试策略。

一些观点

企业级Web项目中应该如何做单元测试、集成测试和功能测试?

Q: 使用Java做企业市场产品开发,应该如何做单元测试, 集成测试和功能测试?是只测试后端服务吗?需不需要做界面的测试?之前和业界某著名咨询公司首席咨询师交流,他说应该多做基于场景的测试,并且尽量测试真实的代码,少打桩,这种说法有什么问题?

A: 并不是单元测试本身不好,而是由于单元测试本身花费的时间量太大,导致真正能够做好单元测试的越来越少。当前很多企业应用开发,根本没有逻辑层,或者说没有明确的领域服务,写出的单元测试用例直接在跑数据库的CRUD,这个基本没有太大的意义。

个人认为单元测试重点一定是要有明确的领域层或服务层,同时单元测试最好也是和CI持续集成配合,即单元测试无法做到100%完全测试用例覆盖,重点还是主体功能覆盖,更好的用于CI中的自动化冒烟测试。

集成测试,能够做好的同样很少,很多集成测试就是在做系统测试,原因在于很多就没有子系统的概念,没有组件化和模块化的概念,接口本身也没有提前定义和设计,谈不上模块的集成和组装。集成测试没做好不是方法的问题,首先还是模块化和接口设计没推进的问题。当有了真正的集成测试,你就会明白stub的使用往往是必须的了,特别是在由顶向下进行的集成的时候。

以上两点都难推进的情况下,那就好好把系统测试做好,你说的是对的,基于业务场景的系统功能测试是最重要的,至少能够交付到客户一个缺陷率低,满足业务需求的产品。

单元测试的好处

A:单元测试最直接的好处有两点:

  • 让你写出更好的代码:职业高内聚、低耦合而且接口设计合理的代码才易于测试
  • 让你在修改代码时更有信心

如何保持unit test代码的稳定

A: 代码是为了什么,当然是为了重复运行。如何保持unit test代码的稳定?主要靠好的API设计。API切实正确切割了需求,那么在重构的时候API就基本不用变化,unit test也不用重写。以后你重构的时候,只要你的unit test覆盖的够好,基本跑一遍就知道有没有改成傻逼。可以节省大量的时间。

所以那些专门写不需要维护的软件的人,讨厌测试,也是情有可原的。

两个PHP项目

BootstrapCMS

项目作者是PHP著名的 Laravel 框架的开发组成员。

octobercms

这个项目的测试文件比较完备,甚至改包括了使用selenium进行UI测试。

参考资料


Fiddler 让 Win10 自带日历客户端连接谷歌账户

作为软件开发者,连接google几乎是我们的必备生存技能。然而在使用win10自带的日历,由于Metro Apps是运行在被隔离的App Containers环境中,该环境阻止了网络流量发送到本机,所以即使有Shadowsock也是连不上的233333(使用vpn则是没有问题的,然而vpn比ss速度毕竟慢一个等级,而且也不能使用pac)。

所以目标是在ss下让Metro Apps连上互联网。虽然没有除了vpn外的直接的办法,可以使用 Fiddler 进行迂回战术达到我们的效果。

参考资料