应对Aviasales的测试开发经验

嗨,我想分享我为Aviasales开发测试用例的经验。


我最近偶然发现了Aviasales的React开发人员工作。 我发送了一份申请,然后第二天HR回答了我,并告知我必须执行测试任务。 我真的不喜欢做测试任务,因为我必须花很多时间来执行它们,如果失败的话,这将被浪费掉。 但是我同意...


您可以在此处的链接中找到测试任务。


这是我完成的任务存储库的链接


我限制自己在一天之内完成作业(尽管发布后确实做了一些小改进:可以说,我完成了草图)。


我为开发选择的是:


  1. 我选择NextJS作为基础,因为我不想修改Webpack的环境,因此您只需单击几下即可部署项目本身。
  2. 我想写得很快,选择与MobX结合使用React-IOC软件包,而不是Redux。 此程序包使您可以通过类似于角度服务的服务编写应用程序。
  3. 我使用了Web Worker,以便在对大量数据进行排序时,界面不会出现延迟。
  4. 我之所以没有使用Typescript,是因为它不会在测试任务上浪费时间,而无需编写其他代码。
  5. 基于第4段,我也没有编写测试。
  6. 我向该项目添加了两个附加软件包:debounce,RxJS。 首先需要创建简单的回调,例如,更改下载状态,以便在下载花费很少时间的情况下微调框不会显示负载。 我总是使用第二个包来创建操作脚本,例如,在向服务器发送请求时出现错误时处理状态。

开发第一阶段的程序:


  1. 初始化的存储库。
  2. 初始化NextJS项目。
  3. 添加了带有Hello World消息的索引基础页。
  4. 创建了一个与api服务器交互的ticket.provider服务。
  5. 创建了ticket.service服务,该服务注入ticket.provider并向观察者填充一系列显示的票证
  6. 创建ticket.filter.service,它存储通过@computed从ticket.service注入的过滤数据

发展的第二阶段:


  1. 使用任务存储库中提供的布局为其创建了组件并绘制了样式。
  2. 我做了下载的微调,并从服务中降低了其价值。
  3. 将所有服务逻辑与组件连接。
  4. 添加了具有数据格式的实用程序,例如时间和金钱。

然后,我决定尝试使用“触摸”界面,并在使用该应用程序时发现了缺陷:


  1. 更改过滤器和排序时,界面会变慢,因此我将数据的存储,检索和过滤转移到了Web Worker中,之后这些滞后完全消失了。
  2. Spinner并没有解决跳线动画,因此我将其替换为带有闪烁动画的可视线条显示。
  3. 为了简化数据渲染,我将数据格式化调用转移到了Web Worker,这减轻了组件渲染的负担

然后,我完成了工作,并在一天结束时发送了任务以进行验证。


由于我限制了自己的时间,因此我没有进一步优化应用程序,即没有使用React.memo(...)。 我也没有开始用服务中的注入器替换窗口和路由器。 为此,请原谅我,这是一个缺陷。


但是第二天,我在浏览器的url行中添加了记住过滤器状态的功能,此后我已经对所做的工作感到满意。


我等待他们的回复7天,他们没有回复我的任何消息。 可以这么说,这是令人不愉快的经历。 但是他们仍然回答,而且阅读的答案非常令人困扰。 该消息可以在下面看到。


让我们看一下要点:


[1]。 “工作非常仔细”


我看不到哪里,没有争论,因为没有例子。


[2]。 “似乎开发追求了“它起作用”的目标,而忽略了“它如何起作用”。


没有争论,没有例子。


[3]。 “根据我们对候选人水平的要求,完成的任务几乎没有达到中间水平。”


有什么要求? 他们在哪


[4]。 “我们希望过滤器不会被硬编码,并将适应数据。 如果您使用aviasales,您会看到在第一批付款出现时便立即显示了票证,我们不会等到每个人都加载。”


此要求不在附加任务中。 在我看来,Aviasales应用程序本身没有参考界面,跳票并不是最佳解决方案。


[5]。 “为什么filter.service知道路由器和窗口? 他根本不应该控制应用程序的状态,而应该完全具有这种依赖性。”


因为创建服务是为了控制整个应用程序或存在它们的模块的状态。 在这里,作者明确建议在组件中编写所有逻辑。


[6]。 “网络工作者。 什么是利润? 在这种情况下,异步操作将花费大量时间,主线程中保存的负载将花费在序列化/反序列化对象(以及可观察对象)上。 如果我们在谈论优化,那么值得一开始的不是从网络工作者中删除,而是在主线程中解决问题。”


如何处理主线程中的大量数据,同时又没有接口滞后? 对于我来说,找出是否有人有一个例子,然后在评论中写下来,将是非常有趣的。 显然我缺少了一些东西。


[7]。 “仅将rxjs添加到项目中以实现重试和顺序加载是没有意义的。”


为什么没有道理? 您可以将严格必要的函数导入RxJS;如果摇摇晃晃的软件包和函数无法正常工作,则不会增加应用程序的大小。


[8]。 “该项目无法扩展和维护。 像(ticket.segments || [{}, {}]).map((ticket) => ...)类的结构(ticket.segments || [{}, {}]).map((ticket) => ...)非常繁琐。”


让我们看一下扩展和支持的标准:可访问性(服务解决了这个问题),风险( ticket.segments || [{}, {}]只是在输入不包含数据的情况下如何处理案例的一个示例。至少可以使用可空结构的方法,但我尝试遵守),干净的代码(嗯,至少我知道它是什么:),尽管我尝试按应有的方式编写所有内容)。 似乎一切都被捕获了,再也不是争论了。


[9]。 “我给人的印象是,对React的幕后工作原理完全不了解。 使用组件的道具时会遇到许多严重错误,这些错误会对性能产生非常不利的影响。 React优化机制被忽略。”


我不明白这些描述的问题在哪里。 什么样的机制?


[10]。 “在渲染器内部创建处理函数。”


我根本没有渲染中的任何处理函数,有人知道这里写的内容吗? 我什至将格式处理转移到了Web Worker


[11]。 “创建一个新的空对象并将其转移到票证。 ticket-list-loading.jsx:10 Ticket.tsx:24 ticket-list-loading.jsx:10Ticket.tsx:24


除了我懒惰地分开收取票务组件之外,这里没有什么要紧的。 传递空对象不会违反任何编程原则,只是在这里必须通过ticket = ticket || {};来完成此操作。 ticket = ticket || {}; 但这完全是由于开发时间限制为一天,并且修复所有次要缺陷需要更多时间。


[12]。 “将数组索引作为票证列表上的键”


还有一个问题,为什么api不返回id为id的元素。 因此,当从服务器接收数据时,我需要为每个元素生成唯一的密钥,这并不是我作为测试任务的一部分,因为即使在实际项目中,这也是一种可疑的方法。


最后,得出结论:“总的来说,React无法正常工作(
总计:对于中层来说,我们期望反应不会有关键问题,但是在完成的工作中有很多问题。”


目前尚无评论...


谢谢,如果您读完了。 我对Aviasales持负面意见,因此我将所有内容张贴在这里,以便您评估自己是否应该联系他们。


消息全文:


这项工作非常仔细。 在开发过程中,目标似乎是“有效”,而“有效方式”被忽略了。 根据我们对候选人级别的要求,完成的任务几乎没有达到中间水平。


性能和结构:
我们希望过滤器不会被硬编码,并且会适应数据。 如果您使用aviasales,您会看到在第一期付款出现时立即显示了票证,我们不等待所有人加载。


此外,还有更多技术要点。


  1. 为什么filter.service知道路由器和窗口? 它不应该控制应用程序的状态,并且完全具有这种依赖性。
  2. 网络工作者。 什么是利润? 在这种情况下,异步操作将花费大量时间,主线程中保存的负载将花费在序列化/反序列化对象(以及可观察对象)上。 如果我们在谈论优化,那么值得一开始的不是从网络工作者中删除,而是在主线程中解决问题。
  3. 仅将rxjs添加到项目中仅用于实现重试和顺序加载是没有意义的。
  4. 该项目无法扩展和维护。 像( ticket.segments || [{}, {}]).map((ticket) => ticket )这样的构造非常麻烦。
    反应:
    我的印象是,对React的幕后工作原理完全没有任何了解。 使用组件的道具时会遇到许多严重错误,这些错误会对性能产生非常不利的影响。 React优化机制被忽略。 简要介绍一下问题:
  5. 在render中创建处理函数。
  6. 创建一个新的空对象并将其传输到票证。 ticket-list-loading.jsx:10 Ticket.tsx:24 ticket-list-loading.jsx:10Ticket.tsx:24
  7. 数组索引作为故障单列表上的键。
    总的来说,React不起作用:(

总计:对于中层来说,我们期望做出反应不会有关键问题,但是完成的工作中有很多。

Source: https://habr.com/ru/post/zh-CN468715/


All Articles