View Javadoc

1   /*
2    * Copyright 2010-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.testdoc.collect.extractor;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  
21  import javax.lang.model.element.Element;
22  import javax.lang.model.element.ElementKind;
23  import javax.lang.model.element.ExecutableElement;
24  import javax.lang.model.element.TypeElement;
25  import javax.lang.model.element.VariableElement;
26  
27  import de.smartics.testdoc.annotations.Uut;
28  import de.smartics.testdoc.collect.extractor.TestDocAnnotationExtractor.UutInfo;
29  import de.smartics.testdoc.core.doc.ScenarioTestDoc;
30  import de.smartics.testdoc.core.doc.UnitTestDoc;
31  
32  /**
33   * Extracts unit test doc information from a specified variable.
34   *
35   * @todo Currently only fields and no inline variables are supported. This is
36   *       due to the fact that the APT parser does not return variable
37   *       information.
38   * @author <a href="mailto:robert.reiner@smartics.de">Robert Reiner</a>
39   * @version $Revision:591 $
40   */
41  public final class TestDocVariableExtractor extends AbstractExtractor
42  {
43    // ********************************* Fields *********************************
44  
45    // --- constants ------------------------------------------------------------
46  
47    // --- members --------------------------------------------------------------
48  
49    /**
50     * The element that contains information about a variable in the test case
51     * class that points to the unit under test.
52     */
53    private final VariableElement declaredUutField;
54  
55    // ****************************** Initializer *******************************
56  
57    // ****************************** Constructors ******************************
58  
59    /**
60     * Default constructor.
61     *
62     * @param config the configuration to access processing information.
63     * @param declaredUutField the element that contains information about a
64     *          variable in the test case class that points to the unit under
65     *          test.
66     * @throws IllegalArgumentException if the <code>declaredUutField</code> is
67     *           not a field declaration within a class or any of the arguments is
68     *           <code>null</code>.
69     * @throws ExtractorException if there is a {@link Uut} annotation at type and
70     *           field level.
71     */
72    public TestDocVariableExtractor(final ExtractorConfig config,
73        final VariableElement declaredUutField) throws IllegalArgumentException,
74      ExtractorException
75    {
76      super(config, initTypeElement(declaredUutField));
77      this.declaredUutField = declaredUutField;
78    }
79  
80    // ****************************** Inner Classes *****************************
81  
82    // ********************************* Methods ********************************
83  
84    // --- init -----------------------------------------------------------------
85  
86    private static void checkArguments(final VariableElement declaredUutField)
87    {
88      if (null == declaredUutField)
89      {
90        throw new IllegalArgumentException(
91            "The field, declared in the test case, that points to the UUT is required.");
92      }
93    }
94  
95    private static TypeElement initTypeElement(
96        final VariableElement declaredUutField) throws IllegalArgumentException,
97      ExtractorException
98    {
99      checkArguments(declaredUutField);
100 
101     Element current = declaredUutField;
102     while (current != null)
103     {
104       final ElementKind kind = current.getKind();
105       if (ElementKind.CLASS.equals(kind))
106       {
107         final TypeElement selected = (TypeElement) current;
108         if (hasAnnotation(selected, Uut.class))
109         {
110           throw new ExtractorException(
111               "Uut annotation not allowed at type and field"
112                   + " level at the same time.");
113         }
114         return selected;
115       }
116       current = current.getEnclosingElement();
117     }
118 
119     throw new IllegalArgumentException("Declaration of UUT '"
120                                        + declaredUutField.asType()
121                                        + "' is not within a test case class.");
122   }
123 
124   // --- get&set --------------------------------------------------------------
125 
126   // --- business -------------------------------------------------------------
127 
128   /**
129    * Reads the test documentation from the element the extractor instance is
130    * associated with.
131    *
132    * @return the test documentation read.
133    */
134   public UnitTestDoc readTestDoc()
135   {
136     final String testCaseType = calcTestCaseType();
137     final UutInfo uutInfo = uutExtractor.read(declaredUutField);
138     final List<ScenarioTestDoc> scenarios =
139         calcScenarios(uutInfo, testCaseType);
140 
141     // We ignore the type information from the UUT annotation.
142     final String uutType = calcUutTypeName();
143 
144     final UnitTestDoc testDoc = new UnitTestDoc(uutType, scenarios);
145 
146     return testDoc;
147   }
148 
149   private String calcTestCaseType()
150   {
151     return testCaseType.asType().toString();
152   }
153 
154   private String calcUutTypeName()
155   {
156     return declaredUutField.asType().toString();
157   }
158 
159   private List<ScenarioTestDoc> calcScenarios(final UutInfo uutInfo,
160       final String testCaseTypeName) throws ExtractorException
161   {
162     final List<ScenarioTestDoc> scenarios = new ArrayList<ScenarioTestDoc>();
163 
164     for (final Element element : elementUtils.getAllMembers(testCaseType))
165     {
166       if (isTestMethodWithoutUutAnnotation(element))
167       {
168         final ExecutableElement testMethod = (ExecutableElement) element;
169         final ScenarioTestDoc scenario =
170             createScenarioIfElementIsTestMethod(uutInfo, testCaseTypeName,
171                 testMethod);
172         if (scenario != null)
173         {
174           scenarios.add(scenario);
175         }
176       }
177     }
178 
179     return scenarios;
180   }
181 
182   // --- object basics --------------------------------------------------------
183 
184 }