Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
6 | class ElasticsearchBaseTest extends SapphireTest { |
||
7 | |||
8 | public static $ignoreFixtureFileFor = array(); |
||
9 | |||
10 | protected $extraDataObjects = array( |
||
11 | 'SearchableTestPage','FlickrPhotoTO','FlickrAuthorTO','FlickrSetTO','FlickrTagTO', |
||
12 | 'SearchableTestFatherPage','SearchableTestGrandFatherPage','AutoCompleteOption' |
||
13 | ); |
||
14 | |||
15 | |||
16 | public function setUpOnce() { |
||
33 | |||
34 | |||
35 | public function setUp() { |
||
|
|||
36 | // no need to index here as it's done when fixtures are loaded during setup method |
||
37 | $cache = SS_Cache::factory('elasticsearch'); |
||
38 | $cache->clean(Zend_Cache::CLEANING_MODE_ALL); |
||
39 | SS_Cache::set_cache_lifetime('elasticsearch', 3600, 1000); |
||
40 | |||
41 | // this needs to be called in order to create the list of searchable |
||
42 | // classes and fields that are available. Simulates part of a build |
||
43 | $classes = array('SearchableTestPage','SiteTree','Page','FlickrPhotoTO','FlickrSetTO', |
||
44 | 'FlickrTagTO', 'FlickrAuthorTO'); |
||
45 | $this->requireDefaultRecordsFrom = $classes; |
||
46 | |||
47 | |||
48 | // clear the index |
||
49 | $this->service = Injector::inst()->create('SilverStripe\Elastica\ElasticaService'); |
||
50 | $this->service->setTestMode(true); |
||
51 | |||
52 | // A previous test may have deleted the index and then failed, so check for this |
||
53 | if (!$this->service->getIndex()->exists()) { |
||
54 | $this->service->getIndex()->create(); |
||
55 | } |
||
56 | $this->service->reset(); |
||
57 | |||
58 | // FIXME - use request getVar instead? |
||
59 | $_GET['progress'] = 20; |
||
60 | // load fixtures |
||
61 | |||
62 | $orig_fixture_file = static::$fixture_file; |
||
63 | |||
64 | View Code Duplication | foreach (static::$ignoreFixtureFileFor as $testPattern) { |
|
65 | $pattern = '/'.$testPattern.'/'; |
||
66 | if (preg_match($pattern, $this->getName())) { |
||
67 | static::$fixture_file = null; |
||
68 | } |
||
69 | } |
||
70 | |||
71 | parent::setUp(); |
||
72 | static::$fixture_file = $orig_fixture_file; |
||
73 | |||
74 | $this->publishSiteTree(); |
||
75 | |||
76 | $this->service->reset(); |
||
77 | |||
78 | // index loaded fixtures |
||
79 | $task = new ReindexTask($this->service); |
||
80 | // null request is fine as no parameters used |
||
81 | |||
82 | $task->run(null); |
||
83 | |||
84 | } |
||
85 | |||
86 | |||
87 | protected function devBuild() { |
||
92 | |||
93 | |||
94 | private function publishSiteTree() { |
||
95 | foreach (SiteTree::get()->getIterator() as $page) { |
||
96 | // temporarily disable Elasticsearch indexing, it will be done in a batch |
||
97 | $page->IndexingOff = true; |
||
98 | $page->publish('Stage','Live'); |
||
99 | } |
||
100 | } |
||
101 | |||
102 | |||
103 | View Code Duplication | public function generateAssertionsFromArray($toAssert) { |
|
112 | |||
113 | |||
114 | View Code Duplication | public function generateAssertionsFromArray1D($toAssert) { |
|
123 | |||
124 | |||
125 | public function generateAssertionsFromArrayRecurse($toAssert) { |
||
130 | |||
131 | |||
132 | private function recurseArrayAssertion($toAssert, $depth, $parentKey) { |
||
155 | |||
156 | |||
157 | /* |
||
158 | Helper methods for testing CMS fields |
||
159 | */ |
||
160 | public function checkTabExists($fields, $tabName) { |
||
176 | |||
177 | |||
178 | public function checkFieldExists($tab,$fieldName) { |
||
184 | |||
185 | |||
186 | /** |
||
187 | * From https://jtreminio.com/2013/03/unit-testing-tutorial-part-3-testing-protected-private-methods-coverage-reports-and-crap/ |
||
188 | * Call protected/private method of a class. |
||
189 | * |
||
190 | * @param object &$object Instantiated object that we will run method on. |
||
191 | * @param string $methodName Method name to call |
||
192 | * @param array $parameters Array of parameters to pass into method. |
||
193 | * |
||
194 | * @return mixed Method return. |
||
195 | */ |
||
196 | public function invokeMethod(&$object, $methodName, array $parameters = array()) |
||
197 | { |
||
198 | $reflection = new \ReflectionClass(get_class($object)); |
||
199 | $method = $reflection->getMethod($methodName); |
||
200 | $method->setAccessible(true); |
||
201 | |||
202 | return $method->invokeArgs($object, $parameters); |
||
203 | } |
||
204 | |||
205 | |||
206 | View Code Duplication | public function checkNumberOfIndexedDocuments($expectedAmount) { |
|
217 | |||
218 | /* |
||
219 | Get the number of documents in an index. It is assumed the index exists, if not the test will fail |
||
220 | */ |
||
221 | View Code Duplication | public function getNumberOfIndexedDocuments() { |
|
233 | } |
||
234 |
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: