AutoTest: fine tune quick test case specs

and fix multiple inheritance

Change-Id: I031c8518437b7b396f5b17a51d2067e4b3661530
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2019-07-30 13:17:35 +02:00
committed by Christian Stenger
parent c020fb6e3e
commit 6e84529a88
3 changed files with 49 additions and 51 deletions

View File

@@ -190,33 +190,33 @@ static bool checkQmlDocumentForQuickTestCode(QFutureInterface<TestParseResultPtr
if (!qmlVisitor.isValid())
return false;
const QVector<QuickTestCaseSpec> &testFunctions = qmlVisitor.testFunctions();
const QVector<QuickTestCaseSpec> &testCases = qmlVisitor.testCases();
for (const QuickTestCaseSpec &it : testFunctions) {
const QString testCaseName = it.m_caseName;
const QString functionName = it.m_functionName;
const TestCodeLocationAndType &loc = it.m_functionLocationAndType;
for (const QuickTestCaseSpec &testCase : testCases) {
const QString testCaseName = testCase.m_caseName;
QuickTestParseResult *parseResult = new QuickTestParseResult(id);
parseResult->proFile = proFile;
parseResult->itemType = TestTreeItem::TestCase;
if (!testCaseName.isEmpty()) {
parseResult->fileName = it.m_name;
parseResult->fileName = testCase.m_locationAndType.m_name;
parseResult->name = testCaseName;
parseResult->line = it.m_line;
parseResult->column = it.m_column;
parseResult->line = testCase.m_locationAndType.m_line;
parseResult->column = testCase.m_locationAndType.m_column;
}
QuickTestParseResult *funcResult = new QuickTestParseResult(id);
funcResult->name = functionName;
funcResult->displayName = functionName;
funcResult->itemType = loc.m_type;
funcResult->fileName = loc.m_name;
funcResult->line = loc.m_line;
funcResult->column = loc.m_column;
funcResult->proFile = proFile;
for (auto function : testCase.m_functions) {
QuickTestParseResult *funcResult = new QuickTestParseResult(id);
funcResult->name = function.m_functionName;
funcResult->displayName = function.m_functionName;
funcResult->itemType = function.m_locationAndType.m_type;
funcResult->fileName = function.m_locationAndType.m_name;
funcResult->line = function.m_locationAndType.m_line;
funcResult->column = function.m_locationAndType.m_column;
funcResult->proFile = proFile;
parseResult->children.append(funcResult);
parseResult->children.append(funcResult);
}
futureInterface.reportResult(TestParseResultPtr(parseResult));
}

View File

@@ -86,34 +86,29 @@ static bool isDerivedFromTestCase(QmlJS::AST::UiQualifiedId *id, const QmlJS::Do
bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
{
const QStringRef name = ast->qualifiedTypeNameId->name;
m_objectStack.push(name.toString());
m_objectIsTestStack.push(false);
if (name != "TestCase") {
m_insideTestCase = false;
if (!isDerivedFromTestCase(ast->qualifiedTypeNameId, m_currentDoc, m_snapshot))
return true;
} else if (!documentImportsQtTest(m_currentDoc.data())) {
return true; // find nested TestCase items as well
}
m_typeIsTestCase = true;
m_insideTestCase = true;
m_objectIsTestStack.top() = true;
const auto sourceLocation = ast->firstSourceLocation();
QuickTestCaseSpec currentSpec;
currentSpec.m_name = m_currentDoc->fileName();
currentSpec.m_line = sourceLocation.startLine;
currentSpec.m_column = sourceLocation.startColumn - 1;
currentSpec.m_type = TestTreeItem::TestCase;
m_testCases.push(currentSpec);
currentSpec.m_locationAndType.m_name = m_currentDoc->fileName();
currentSpec.m_locationAndType.m_line = sourceLocation.startLine;
currentSpec.m_locationAndType.m_column = sourceLocation.startColumn - 1;
currentSpec.m_locationAndType.m_type = TestTreeItem::TestCase;
m_caseParseStack.push(currentSpec);
return true;
}
void TestQmlVisitor::endVisit(QmlJS::AST::UiObjectDefinition *)
{
if (!m_objectStack.isEmpty() && m_objectStack.pop() == "TestCase") {
if (!m_testCases.isEmpty())
m_testCases.pop();
m_insideTestCase = !m_objectStack.isEmpty() && m_objectStack.top() == "TestCase";
}
if (!m_objectIsTestStack.isEmpty() && m_objectIsTestStack.pop() && !m_caseParseStack.isEmpty())
m_testCases << m_caseParseStack.pop();
}
bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast)
@@ -124,7 +119,7 @@ bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast)
bool TestQmlVisitor::visit(QmlJS::AST::UiScriptBinding *ast)
{
if (m_insideTestCase)
if (m_objectIsTestStack.top())
m_expectTestCaseName = ast->qualifiedId->name == "name";
return m_expectTestCaseName;
}
@@ -137,6 +132,9 @@ void TestQmlVisitor::endVisit(QmlJS::AST::UiScriptBinding *)
bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
{
if (m_caseParseStack.isEmpty())
return false;
const QStringRef name = ast->name;
if (name.startsWith("test_")
|| name.startsWith("benchmark_")
@@ -154,13 +152,8 @@ bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
else
locationAndType.m_type = TestTreeItem::TestFunction;
if (m_testCases.isEmpty()) // invalid qml code
return false;
QuickTestCaseSpec testCaseWithFunc = m_testCases.top();
testCaseWithFunc.m_functionName = name.toString();
testCaseWithFunc.m_functionLocationAndType = locationAndType;
m_testFunctions.append(testCaseWithFunc);
m_caseParseStack.top().m_functions.append(
QuickTestFunctionSpec{name.toString(), locationAndType});
}
return false;
}
@@ -168,8 +161,8 @@ bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
bool TestQmlVisitor::visit(QmlJS::AST::StringLiteral *ast)
{
if (m_expectTestCaseName) {
QTC_ASSERT(!m_testCases.isEmpty(), return false);
m_testCases.top().m_caseName = ast->value.toString();
QTC_ASSERT(!m_caseParseStack.isEmpty(), return false);
m_caseParseStack.top().m_caseName = ast->value.toString();
m_expectTestCaseName = false;
}
return false;

View File

@@ -37,12 +37,19 @@
namespace Autotest {
namespace Internal {
class QuickTestCaseSpec : public TestCodeLocationAndType
class QuickTestFunctionSpec
{
public:
QString m_functionName;
TestCodeLocationAndType m_locationAndType;
};
class QuickTestCaseSpec
{
public:
QString m_caseName;
QString m_functionName;
TestCodeLocationAndType m_functionLocationAndType;
TestCodeLocationAndType m_locationAndType;
QVector<QuickTestFunctionSpec> m_functions;
};
class TestQmlVisitor : public QmlJS::AST::Visitor
@@ -58,17 +65,15 @@ public:
bool visit(QmlJS::AST::FunctionDeclaration *ast) override;
bool visit(QmlJS::AST::StringLiteral *ast) override;
QVector<QuickTestCaseSpec> testFunctions() const { return m_testFunctions; }
bool isValid() const { return m_typeIsTestCase; }
QVector<QuickTestCaseSpec> testCases() const { return m_testCases; }
bool isValid() const { return !m_testCases.isEmpty(); }
private:
QmlJS::Document::Ptr m_currentDoc;
QmlJS::Snapshot m_snapshot;
QStack<QuickTestCaseSpec> m_testCases;
QVector<QuickTestCaseSpec> m_testFunctions;
QStack<QString> m_objectStack;
bool m_typeIsTestCase = false;
bool m_insideTestCase = false;
QStack<QuickTestCaseSpec> m_caseParseStack;
QVector<QuickTestCaseSpec> m_testCases;
QStack<bool> m_objectIsTestStack;
bool m_expectTestCaseName = false;
};