写测试前需要准备的东西

  1. 默认数据需要准备
    一些数据是需要提前准备的,例如角色数据、分类数据。

1.1 表结构
在使用Laravel的时候,需要注意要先创建表结构。
如果是用原生的Laravel搭建的系统还好,每个表结构都应该有对应的migration。
但是在诸如Voyager等CMS的时候,可能并不会创建migration文件。
此时需要使用例如laravel-migrations-generator的反向migrator生成器。他可以根据表结构生成migration文件。
用此类工具的时候需要注意:由于是以当前时间点表结构创建的migration,如果自己还有写一些migration,那么要注意冲突或者字段不存在的情况。
例如:我写了migration在user表的avatar字段后面添加status字段,但是用该扩展生成的migration文件里已经包含了status字段。如果再跑这个migration,就会报该字段已存在的错误。

1.2 初始数据
用seeder可以插入默认数据。我使用了orangehill/iseed这个扩展来生成初始数据。
这里要注意一点,由于它是根据表名的顺序来生成seeder的,如果使用了外键约束,那么在往前面的表插入数据的时候会报关联错误Integrity constraint violation。

  1. 分清楚要测试的模块、分清楚测试的先后顺序。
    订单都没有,也不可能测支付。
  2. 写清楚每个测试的步骤
    例如,先创建才能编辑/删除。

Laravel6 启动dusk时遇到JSON decoding of remote response failed

今天第一次使用Laravel Dusk来写UI测试。

按照文档安装好dusk,使用php artisan dusk尝试跑测试后,报了以下错误:

Facebook\WebDriver\Exception\WebDriverException: JSON decoding of remote response failed.
Error code: 4
The response: ''

搜索了一圈,在这个链接找到一个解决方法。需要先用./vendor/laravel/dusk/bin/chromedriver-mac-intel --port=9515这个命令启动chrome,再跑php artisan dusk才可以。(我用的是Intel版的mac,其他版本有对应的chrome driver)

我觉得很奇怪,dusk命令居然还要我手动启动chrome的吗?

后来试了一下关闭启动了的chromedriver,并在dusk命令前添加了sudo:sudo php artisan dusk
果然代码可以跑通了。

但我看chromedriver-mac-intel文件是-rwxr-xr-x,不应该启动不了啊?

在网上搜索了一圈,说要用php artisan dusk:chrome-driver --proxy=0.0.0.0:8888命令先安装chrome driver,但文件是存在的。太奇怪了。安装了之后,再跑php artisan dusk,现在报的错就不一样了:

Facebook\WebDriver\Exception\UnknownErrorException: unknown error: Chrome failed to start: exited abnormally.
  (unknown error: DevToolsActivePort file doesn't exist)
  (The process started from chrome location ./vendor/laravel/dusk/bin/chromedriver-mac-intel is no longer running, so ChromeDriver is assuming that Chrome has crashed.)

在网上搜索了第二圈,说安装了之后要重启才行。俗话说重启大法好,那我就重启看看吧。

重启之后果然就好了……

docker初探

好吧,其实这个标题是假的。
我在不知不觉中已经用了很多次docker了。
但是docker的构建,编译和运行大部分是同事完成的。

还有很多docker的知识我还不是很懂,所以打算借此机会学习一下。
会参考一些教程网站,例如:

  1. Docker入门教程(一)介绍
  2. Docker中文社区站-Docker入门教程

首先,运行任何"docker"(容器),都需要两个步骤:

  1. 构建镜像
  2. 运行容器

整个过程可以简单地理解为写代码打包(构建镜像),双击在本地运行(运行容器)。
构建镜像可以理解为"docker"(容器)是编译型语言,类似Java,C/C++,需要先编译。
其次,编译完的可执行文件需要双击才能运行,光编译完没啥用,除了拿来发布。

镜像有什么用呢,其实就是自己打包好的环境。
现在我的笔记本(win)就因为我之前瞎鼓捣些项目,有些环境又不是很完善,整个环境有些乱了。
鼓捣完了之后,又不舍得卸载,而且还卸不干净。

如果你把你搭建好的环境打包放出去给别人下载,其他人就不用重复踩你踩过的坑了。
而且随用随下,用毕即弃。是不是听起来好像一次性餐具?但是这是电子世界,你丢弃一次性01串不会造成污染(用电的不算)。

好了,说了那么多废话,继续回到话题上来。

现在我们就先不讲构建镜像了。我们先用别人构建好的镜像。
先跑这个命令下载镜像:docker pull ubuntu
我此时下载的镜像是这样的,随版本更新,以下hash值会不一样。

Using default tag: latest
latest: Pulling from library/ubuntu
75c416ea735c: Pull complete
c6ff40b6d658: Pull complete
a7050fc1f338: Pull complete
f0ffb5cf6ba9: Pull complete
be232718519c: Pull complete
Digest: sha256:a0ee7647e24c8494f1cf6b94f1a3cd127f423268293c25d924fbe18fd82db5a4
Status: Downloaded newer image for ubuntu:latest

docker images就可以看到你下载过的镜像。

REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
ubuntu                 latest              d355ed3537e9        14 hours ago        119 MB

好,我们现在让它跑起来:docker run -it ubuntu bash
可以看到命令行变成root@4d3f61c27b6c:/#了。
这个时候,你可以敲任何ubuntu命令了。

这条命令的意思是,在ubuntu这个镜像上run(运行)bash这条命令。
-it呢,等于-i -t
-i就是Keep STDIN open even if not attached,就是交互模式。
-t就是Allocate a pseudo-TTY,分配一个虚拟TTY?
-t参数模拟ssh登陆容器(这个描述应该不准确),然后用-i参数来接受来自用户的输入`。

我尝试了一下,如果只有-i参数,那它会啥都不输出。
虽然是交互模式,但是没有tty,所以输出内容不会传输过来到宿主机。
如果只有-t参数,虽然有输出,但是无法接收来自用户的输入。
但是-it(或者-ti)就即能接收用户的输入,也可以显示容器的输出(这个描述应该也不准确)。

你大概已经折腾了一天,该睡觉了吧?
在linux里敲exit就可以退出bash。

咦?那我明天也运行docker run -it ubuntu bash就好了吗?
你可以试试啊~进入linux后,你会发现你昨天做的改动都没有了。
机子名也变了。敲exit退出。

在宿主机(安装了docker的机子)敲docker ps -a就可以看到,我们刚刚运行的容器已经结束了。

λ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
0e152599996f        ubuntu              "bash"              45 seconds ago      Exited (0) 1 second ago                        naughty_wilson
4d3f61c27b6c        ubuntu              "bash"              3 minutes ago       Exited (0) 2 minutes ago                       happy_shockley

这里的-a表示all,不带-a的情况下,只会显示正在运行的容器。

如果要它一直运行下去的话怎么办?
这里就先留个问题给读者。(其实是我要睡觉了)

格式化所有项目里的所有php文件

  1. 先列出所有php文件,保存到php.txt中。git ls-files |grep \.php$ > php.txt
  2. phpfmt插件目录拷贝fmt.phar到项目根目录。
  3. 保存一下文件为format.sh
#!/bin/bash
while IFS= read -r file
do
    [ -f "$file" ] && php fmt.phar --psr2 --smart_linebreak_after_curly "$file" #php-cs-fixer fix --rules=@PSR2,-phpdoc_align,@Symfony,-unary_operator_spaces --rules='{"concat_space":{"spacing":"one"}}' "$file"
done < "./php.txt"
  1. bash format.sh就好了。