在SF3.4及以上版本中运行Symfony DIC烟雾测试

在SF3.4及以上版本中运行Symfony DIC烟雾测试

问题描述:

来自DI容器的提取服务是我测试套件中烟雾测试的一个组成部分。例如,下面的测试确保在集装箱中注册的服务的构建没有问题,并且这些服务不需要太多的时间进行施工。在SF3.4及以上版本中运行Symfony DIC烟雾测试

private const DEFAULT_TRESHOLD = 30; 

public function testServicesLoadInTime() 
{ 
    $client = static::createClient(); 

    /** 
    * Add serviceid as key, possible values: 
    * - false: Skip test for this service 
    * - integer value: Custom responsetime 
    */ 
    $customCriteria = [ 
     // See: https://github.com/symfony/monolog-bundle/issues/192 
     'monolog.activation_strategy.not_found' => false, 
     'monolog.handler.fingers_crossed.error_level_activation_strategy' => false, 
     // Should not be used directly (Factories will inject other parameters) 
     'liip_imagine.binary.loader.prototype.filesystem' => false, 
     // Services that are allowed to load longer (Only for CLI tasks like workers) 
     'assetic.asset_manager' => 1000, 
    ]; 

    foreach ($client->getContainer()->getServiceIds() as $id) { 
     if (isset($customCriteria[$id]) && $customCriteria[$id] === false) { 
      continue; 
     } 
     try { 
      $startedAt = microtime(true); 
      $service = $client->getContainer()->get($id); 
      $elapsed = (microtime(true) - $startedAt) * 1000; 
      $this->assertNotNull($service); 
      $treshold = $customCriteria[$id] ?? self::DEFAULT_TRESHOLD; 
      $this->assertLessThan($treshold, $elapsed, sprintf(
       'Service %s loaded in %d ms which is more than the %d ms threshold', 
       $id, $elapsed, $treshold 
      )); 
     } catch (InactiveScopeException $e) { 
      // Noop 
     } catch (\Throwable $ex) { 
      $this->fail(sprintf("Fetching service %s failed: %s", $id, $ex->getMessage())); 
     } 
    } 
} 

但是, Symfony的第4版将使services private by default。即将推出的版本3.4将在服务未标记为公开时使用get()方法从服务容器中获取服务时触发弃用警告。

这让我想知道是否有一种方法可以在不创建公共服务的情况下运行冒烟测试,该服务将所有服务作为构造函数参数进行运行,这与容器中的近1000个服务相距不远,不是一个可行的选项。

您可以为您的服务进行自定义配置,仅用于公开设置所有内容的测试环境。或者,您可以别名您想要测试的服务(在您的测试环境中)。

问题是您将改变每个环境下容器的编译方式,因此检索服务花费多长时间的指标可能不再有用。好消息是,它并不是特别有用,因为没有什么可以真正做到的,因为它很慢并且带有opcache,它不应该成为问题。

对于有烟雾测试,确保服务是可用的,使他们在测试环境中公开的罚款(对我来说)是好的,或者你可以使用WebTestCase通过UI进行烟雾测试。通过确保您的路由可访问,您可以间接确保由于无法访问/配置错误的服务而导致没有500个错误。

当涉及到容器服务的功能测试时,我认为没有办法让它们公开或别名(只在必要时才进行测试)。

+0

快速添加:当您想设置加载时间限制时,使用WebTestCase通过UI测试服务的可用性也更加有用,因为页面加载速度作为度量标准可能更有用。通过这种方式,您可以分析和检查导致性能问题的具体原因并解决具体问题,而不是在服务容器中的某处进行模糊和可疑的微观优化。 ;) – dbrumann

+0

Offtopic:我同意烟雾测试路线也很重要。但是,检查服务的加载时间可以检测在构造函数或依赖项的构造函数中完成许多工作的位置。这可能是延迟加载服务的动机。它让我发现了一个不必要的阻塞curl调用,它在每个页面加载时触发的依赖关系树中深处,但几乎不需要。 – Xatoo

+0

现在我通过加载其他所有服务默认为公共的环境来修复它。我得到的客户端:''客户端=静态:: createClient(['环境'=>'测试']);''和我的测试。yml环境配置包含:''services: _defaults:{public:true}' – Xatoo

我有一个类似的烟雾测试(这使我可以在现在之前发现问题) - 但没有时间的元素。我的'私人'服务列表已经越来越长,没有某种形式的->getContainer()->isPrivate($id)将继续这样做。

仍然会有一些公共服务,我创建或从框架,所以我很高兴将它们添加到排除列表,因为它们出现。