审阅 CSS Animations 测试案例

背景

谢云霄针对 CSS Animations 属性能够应用到 ::before 和 ::after 伪元素 上 这一规范描述,提交了几个测试案例给 W3C CSS 工作组。近20天过去了(期间有中国农历新年假期),这些测试案例并没有得到社区的审阅,所以我就花些时间来审阅它们,同时审阅 CSS Animations 测试套件是否完善。脑中有几个问题:

遗憾的是谢云霄因家庭原因离开了项目组,感谢他的同时,这篇文章还意在帮助新来的同学尽快地融入项目,进而改进这些测试案例,完善 CSS 动画测试套件。

谢云霄提交的测试案例

Pull Request Animation Property Name Animation Property Value Applies to
#728 animation-timing-function cubic-bezir, ease-in-out, ease-in, ease-out, ease ::before, ::after
#727 animation-play-state paused, running ::before, ::after
#726 animation-name none ::before, ::after
#725 animation-iteration-count infinite, number ::before, ::after
#724 animation-fill-mode backwards, both, forwards, none ::before, ::after
#720 animation-duration time ::before, ::after
#717 animation-direction alternate, alternate-reverse, normal, reverse ::before, ::after
#710 animation-delay time ::before, ::after

测试案例分析

整体上,这些测试案例依据动画属性值枚举和两个伪元素的组合,构成 <animation-property-name>-<animation-property-value>-pseudo-before<animation-property-name>-<animation-property-value>-pseudo-after 这样的测试。直观上,这些测试点无可厚非,也符合测试习惯。然而,考虑到 CSS 工作组现有的测试案例都是以 <animation-property-name>-001<animation-property-name>-002 这样的方式命名,新添加的这些测试案例文件还是以序重命名为好,如 animation-delay-004。即 重命名测试文件

这些测试案例依据最新发布版本(2013年2月19日)的规范 http://www.w3.org/TR/css3-animations/ 来编写的;然而考虑到最新编辑版本(2015年2月24日)的规范 http://dev.w3.org/csswg/css-animations-1/ 已经有些许更新,还是以后者为好。即 更新测试文件中的规范链接,甚至可能根据最新规范更新测试案例

纵观整个规范文档,和这两个伪元素相关的内容只有:

Applies to: all elements, ::before and ::after pseudo-elements

我想,这也是这些测试案例的测试依据。然而,测试案例本身并不直观地反映这一点。以 animation-play-state-paused-pseudo-after.html 为例,主要代码如下:

<style>
#content {
  border: 1px solid black;
  width: 150px;
}
#test::after {
  content: "::after";
}
#test {
  position: relative;
  animation-name: sample;
  animation-duration: 5s;
  animation-play-state: paused;
}
@keyframes sample {
  from {
    left: 150px;
  }
  to {
    left: 0px;
  }
}
</style>
<body>
  <p>Test passes if the '::after' doesn't move.</p>
  <div id="test"></div>
</body>

Animation 的相关属性并没有直接应用到 ::after 伪元素上,而是应用到伪元素的原始元素即 idtest<div> 元素上。从几个浏览器的测试结果上看,和直接作用在伪元素上是一致的。这有些让人费解。遇到这样费解的问题,通常会重读规范,看看浏览器的实现是否合乎规范。

::before 和 ::after 伪元素的规范上有这么一段:

They inherit any inheritable properties from their originating element; non-inheritable properties take their initial values as usual.

原来伪元素可以继承它原始元素里可继承的属性! CSS Animations 规范上有这么一段:

In addition to the property-specific values listed in their definitions, all properties defined in this specification also accept the initial and inherit keyword as their property value. For readability it has not been repeated explicitly.

原来如此!这样就可以解释通了,设置在 #test 上的动画属性,被继承到了 #test::after!然而,这样的写法,使得测试案例逻辑结构复杂了。即 可以简化测试案例逻辑,将动画属性直接应用到伪元素上

回头再看这个测试代码,仍有如下问题:

工作组现有测试案例

CSS 工作组目前有 32 个测试文件;然而规范中说有 19 个测试案例工作组运行的结果有 47 个测试案例。这其中定有统计接口不一致的地方,但它不是本节讨论的重点。本节主要关注这 32 个测试文件有哪些可以改进的地方。

首先,http://test.csswg.org/source/css-animations-1/ 所显示的 Description 来源于测试文件中 <title> 的内容,但需要遵从 [Test Area]: [Title/Scope of Test] 这样的格式这便是可以改进的地方之一

其他可以优化的部分,我观测下来主要包括:

Crosswalk 现有测试案例

Crosswalk 测试套件里保有的内部测试案例,如果不能提交给 CSS 工作组,就可以删除了;请新来的同学逐个分析。

深入理解动画规范

要完全理解 CSS 动画规范,一方面要通读规范本身,编写相应的测试案例或者演示示例;另一方面,要对该规范所引用的规范内容,进行必要的研读。

动画规范测试空白

规范第2部分initialinherit 关键字,目前没有测试案例。

In addition to the property-specific values listed in their definitions, all properties defined in this specification also accept the initial and inherit keyword as their property value.

规范第3部分关于 display 属性对动画的影响,也没有得到检验。

Setting the display property to none will terminate any running animation applied to the element and its descendants. If an element has a display of none, updating display to a value other than none will start all animations applied to the element by the animation-name property, as well as all animations applied to descendants with display other than none.

规范第4.1部分,没有得到充分的测试。比如可以将示例4改编为测试案例,测试下面两个测试点:

A keyframe style rule may also declare the timing function.

A timing function specified on the to or 100% keyframe is ignored.

规范第5部分,可以构造一些基于 testharness.js 的测试案例,来测试这些事件构造、事件本身及其属性。参考 DeviceLightEvent,当然可以不需要那么多。这其中,可以探索是否可以通过构建 JS 事件 animationstartanimationendanimationiteration 来模拟 CSS 动画效果。

研读引用文档相关内容

若要完全理解 CSS 动画规范,得了解它所引用的相关规范内容: