on master help sign in
Add tests for the Wolfram Alpha engines (both API and NO API versions)
commitbe54e5269a982e272e2fe8a5064ed898373c9063 authora01200356 <a01200356@itesm.mx> dateWed 30 Dec 2015, 00:53 (11 years ago) parent5ed8f4d
5 files changed+539−8
searx/engines/wolframalpha_api.py+7−4 searx/engines/wolframalpha_noapi.py+6−4 searx/tests/engines/test_wolframalpha_api.py+292 searx/tests/engines/test_wolframalpha_noapi.py+232 searx/tests/test_engines.py+2
searx/engines/wolframalpha_api.py+7−4
@@ -48,13 +48,16 @@ def response(resp):
4848 if search_results.xpath('/queryresult[attribute::success="false"]'):
4949 return []
5050
51− # parse result
52− result = search_results.xpath('//pod[attribute::primary="true"]/subpod/plaintext')[0].text
53− result = replace_pua_chars(result)
51+ # parse answer
52+ answer = search_results.xpath('//pod[attribute::primary="true"]/subpod/plaintext')
53+ if not answer:
54+ return results
55+
56+ answer = replace_pua_chars(answer[0].text)
5457
5558 # append result
5659 # TODO: shouldn't it bind the source too?
57− results.append({'answer': result})
60+ results.append({'answer': answer})
5861
5962 # return results
6063 return results
searx/engines/wolframalpha_noapi.py+6−4
@@ -7,8 +7,8 @@
77# @stable no
88# @parse answer
99
10−import re
11−import json
10+from re import search
11+from json import loads
1212from urllib import urlencode
1313
1414# search-url
@@ -26,6 +26,8 @@ def request(query, params):
2626# get response from search-request
2727def response(resp):
2828 results = []
29+ webpage = resp.text
30+ line = None
2931
3032 # the answer is inside a js function
3133 # answer can be located in different 'pods', although by default it should be in pod_0200
@@ -35,7 +37,7 @@ def response(resp):
3537 # get line that matches the pattern
3638 for pattern in possible_locations:
3739 try:
38− line = re.search(pattern, resp.text).group(1)
40+ line = search(pattern, webpage).group(1)
3941 break
4042 except AttributeError:
4143 continue
@@ -45,7 +47,7 @@ def response(resp):
4547
4648 # extract answer from json
4749 answer = line[line.find('{'):line.rfind('}')+1]
48− answer = json.loads(answer.encode('unicode-escape'))
50+ answer = loads(answer.encode('unicode-escape'))
4951 answer = answer['stringified'].decode('unicode-escape')
5052
5153 results.append({'answer': answer})
searx/tests/engines/test_wolframalpha_api.pynew file+292
@@ -0,0 +1,292 @@
1+# -*- coding: utf-8 -*-
2+from collections import defaultdict
3+import mock
4+from searx.engines import wolframalpha_api
5+from searx.testing import SearxTestCase
6+
7+
8+class TestWolframAlphaAPIEngine(SearxTestCase):
9+
10+ def test_request(self):
11+ query = 'test_query'
12+ api_key = 'XXXXXX-XXXXXXXXXX'
13+ dicto = defaultdict(dict)
14+ dicto['api_key'] = api_key
15+ params = wolframalpha_api.request(query, dicto)
16+
17+ self.assertIn('url', params)
18+ self.assertIn(query, params['url'])
19+ self.assertIn('wolframalpha.com', params['url'])
20+
21+ self.assertIn('api_key', params)
22+ self.assertIn(api_key, params['api_key'])
23+
24+ def test_response(self):
25+ self.assertRaises(AttributeError, wolframalpha_api.response, None)
26+ self.assertRaises(AttributeError, wolframalpha_api.response, [])
27+ self.assertRaises(AttributeError, wolframalpha_api.response, '')
28+ self.assertRaises(AttributeError, wolframalpha_api.response, '[]')
29+
30+ xml = '''<?xml version='1.0' encoding='UTF-8'?>
31+ <queryresult success='false' error='false' />
32+ '''
33+
34+ response = mock.Mock(content=xml)
35+ self.assertEqual(wolframalpha_api.response(response), [])
36+
37+ xml = """<?xml version='1.0' encoding='UTF-8'?>
38+ <queryresult success='false'
39+ error='false'
40+ numpods='0'
41+ datatypes=''
42+ timedout=''
43+ timedoutpods=''
44+ timing='0.241'
45+ parsetiming='0.074'
46+ parsetimedout='false'
47+ recalculate=''
48+ id=''
49+ host='http://www5a.wolframalpha.com'
50+ server='56'
51+ related=''
52+ version='2.6'>
53+ <tips count='1'>
54+ <tip text='Check your spelling, and use English' />
55+ </tips>
56+ </queryresult>
57+ """
58+
59+ response = mock.Mock(content=xml)
60+ self.assertEqual(wolframalpha_api.response(response), [])
61+
62+ xml = """<?xml version='1.0' encoding='UTF-8'?>
63+ <queryresult success='true'
64+ error='false'
65+ numpods='6'
66+ datatypes=''
67+ timedout=''
68+ timedoutpods=''
69+ timing='0.826'
70+ parsetiming='0.17'
71+ parsetimedout='false'
72+ recalculate=''
73+ id='MSPa9721hfe10fii5idac02000029c3a6f09608410h'
74+ host='http://www4c.wolframalpha.com'
75+ server='53'
76+ related='http://www4c.wolframalpha.com/api/v2/relatedQueries.jsp?id=MSPa9731h927ig0h6b1&amp;s=53'
77+ version='2.6'>
78+ <pod title='Input'
79+ scanner='Identity'
80+ id='Input'
81+ position='100'
82+ error='false'
83+ numsubpods='1'>
84+ <subpod title=''>
85+ <img src='http://www4c.wolframalpha.com/Calculate/MSP/MSP974111ig68hc?MSPStoreType=image/gif&amp;s=53'
86+ alt='sqrt(-1)'
87+ title='sqrt(-1)'
88+ width='36'
89+ height='20' />
90+ <plaintext>sqrt(-1)</plaintext>
91+ </subpod>
92+ </pod>
93+ <pod title='Result'
94+ scanner='Simplification'
95+ id='Result'
96+ position='200'
97+ error='false'
98+ numsubpods='1'
99+ primary='true'>
100+ <subpod title=''>
101+ <img src='http://www4c.wolframalpha.com/Calculate/MSP/MSP9751hfe101fc27?MSPStoreType=image/gif&amp;s=53'
102+ alt='i'
103+ title='i'
104+ width='5'
105+ height='18' />
106+ <plaintext>i</plaintext>
107+ </subpod>
108+ <states count='1'>
109+ <state name='Step-by-step solution'
110+ input='Result__Step-by-step solution' />
111+ </states>
112+ </pod>
113+ <pod title='Polar coordinates'
114+ scanner='Numeric'
115+ id='PolarCoordinates'
116+ position='300'
117+ error='false'
118+ numsubpods='1'>
119+ <subpod title=''>
120+ <img src='http://www4c.wolframalpha.com/Calculate/MSP/MSP97600003i83?MSPStoreType=image/gif&amp;s=53'
121+ alt='r = 1 (radius), theta = 90° (angle)'
122+ title='r = 1 (radius), theta = 90° (angle)'
123+ width='209'
124+ height='18' />
125+ <plaintext>r = 1 (radius), theta = 90° (angle)</plaintext>
126+ </subpod>
127+ </pod>
128+ <pod title='Position in the complex plane'
129+ scanner='Numeric'
130+ id='PositionInTheComplexPlane'
131+ position='400'
132+ error='false'
133+ numsubpods='1'>
134+ <subpod title=''>
135+ <img src='http://www4c.wolframalpha.com/Calculate/MSP/MSP9771e10ficg4g?MSPStoreType=image/gif&amp;s=53'
136+ alt=''
137+ title=''
138+ width='200'
139+ height='185' />
140+ <plaintext></plaintext>
141+ </subpod>
142+ </pod>
143+ <pod title='All 2nd roots of -1'
144+ scanner='RootsOfUnity'
145+ id=''
146+ position='500'
147+ error='false'
148+ numsubpods='2'>
149+ <subpod title=''>
150+ <img src='http://www4c.wolframalpha.com/Calculate/MSP/MSP9781hfe10fii?MSPStoreType=image/gif&amp;s=53'
151+ alt='i (principal root)'
152+ title='i (principal root)'
153+ width='94'
154+ height='18' />
155+ <plaintext>i (principal root)</plaintext>
156+ </subpod>
157+ <subpod title=''>
158+ <img src='http://www4c.wolframalpha.com/Calculate/MSP/MSP9791hfe16f2eh1?MSPStoreType=image/gif&amp;s=53'
159+ alt='-i'
160+ title='-i'
161+ width='16'
162+ height='18' />
163+ <plaintext>-i</plaintext>
164+ </subpod>
165+ </pod>
166+ <pod title='Plot of all roots in the complex plane'
167+ scanner='RootsOfUnity'
168+ id='PlotOfAllRootsInTheComplexPlane'
169+ position='600'
170+ error='false'
171+ numsubpods='1'>
172+ <subpod title=''>
173+ <img src='http://www4c.wolframalpha.com/Calculate/MSP/MSP9801h0fi192f9?MSPStoreType=image/gif&amp;s=53'
174+ alt=''
175+ title=''
176+ width='200'
177+ height='185' />
178+ <plaintext></plaintext>
179+ </subpod>
180+ </pod>
181+ </queryresult>
182+ """
183+ response = mock.Mock(content=xml)
184+ results = wolframalpha_api.response(response)
185+ self.assertEqual(type(results), list)
186+ self.assertEqual(len(results), 1)
187+ self.assertIn("i", results[0]['answer'])
188+
189+ xml = """<?xml version='1.0' encoding='UTF-8'?>
190+ <queryresult success='true'
191+ error='false'
192+ numpods='2'
193+ datatypes=''
194+ timedout='Integral'
195+ timedoutpods=''
196+ timing='1.245'
197+ parsetiming='0.194'
198+ parsetimedout='false'
199+ recalculate='http://www4b.wolframalpha.com/api/v2/recalc.jsp?id=MSPa77651gf1a1hie0ii051ea0e1c&amp;s=3'
200+ id='MSPa77661gf1a1hie5c9d9a600003baifafc1211daef'
201+ host='http://www4b.wolframalpha.com'
202+ server='3'
203+ related='http://www4b.wolframalpha.com/api/v2/relatedQueries.jsp?id=MSPa77671gf1a1hie5c5hc2&amp;s=3'
204+ version='2.6'>
205+ <pod title='Indefinite integral'
206+ scanner='Integral'
207+ id='IndefiniteIntegral'
208+ position='100'
209+ error='false'
210+ numsubpods='1'
211+ primary='true'>
212+ <subpod title=''>
213+ <img src='http://www4b.wolframalpha.com/Calculate/MSP/MSP776814b9492i9a7gb16?MSPStoreType=image/gif&amp;s=3'
214+ alt=' integral 1/x dx = log(x)+constant'
215+ title=' integral 1/x dx = log(x)+constant'
216+ width='182'
217+ height='36' />
218+ <plaintext> integral 1/x dx = log(x)+constant</plaintext>
219+ </subpod>
220+ <states count='1'>
221+ <state name='Step-by-step solution'
222+ input='IndefiniteIntegral__Step-by-step solution' />
223+ </states>
224+ <infos count='1'>
225+ <info text='log(x) is the natural logarithm'>
226+ <img src='http://www4b.wolframalpha.com/Calculate/MSP/MSP77691g23eg440g89db?MSPStoreType=image/gif&amp;s=3'
227+ alt='log(x) is the natural logarithm'
228+ title='log(x) is the natural logarithm'
229+ width='198'
230+ height='18' />
231+ <link url='http://reference.wolfram.com/mathematica/ref/Log.html'
232+ text='Documentation'
233+ title='Mathematica' />
234+ <link url='http://functions.wolfram.com/ElementaryFunctions/Log'
235+ text='Properties'
236+ title='Wolfram Functions Site' />
237+ <link url='http://mathworld.wolfram.com/NaturalLogarithm.html'
238+ text='Definition'
239+ title='MathWorld' />
240+ </info>
241+ </infos>
242+ </pod>
243+ <pod title='Plots of the integral'
244+ scanner='Integral'
245+ id='Plot'
246+ position='200'
247+ error='false'
248+ numsubpods='2'>
249+ <subpod title=''>
250+ <img src='http://www4b.wolframalpha.com/Calculate/MSP/MSP77701gf1a9d2eb630g9?MSPStoreType=image/gif&amp;s=3'
251+ alt=''
252+ title=''
253+ width='334'
254+ height='128' />
255+ <plaintext></plaintext>
256+ <states count='1'>
257+ <statelist count='2'
258+ value='Complex-valued plot'
259+ delimiters=''>
260+ <state name='Complex-valued plot'
261+ input='Plot__1_Complex-valued plot' />
262+ <state name='Real-valued plot'
263+ input='Plot__1_Real-valued plot' />
264+ </statelist>
265+ </states>
266+ </subpod>
267+ <subpod title=''>
268+ <img src='http://www4b.wolframalpha.com/Calculate/MSP/MSP77711gf1ai29a34b0ab?MSPStoreType=image/gif&amp;s=3'
269+ alt=''
270+ title=''
271+ width='334'
272+ height='133' />
273+ <plaintext></plaintext>
274+ <states count='1'>
275+ <statelist count='2'
276+ value='Complex-valued plot'
277+ delimiters=''>
278+ <state name='Complex-valued plot'
279+ input='Plot__2_Complex-valued plot' />
280+ <state name='Real-valued plot'
281+ input='Plot__2_Real-valued plot' />
282+ </statelist>
283+ </states>
284+ </subpod>
285+ </pod>
286+ </queryresult>
287+ """
288+ response = mock.Mock(content=xml)
289+ results = wolframalpha_api.response(response)
290+ self.assertEqual(type(results), list)
291+ self.assertEqual(len(results), 1)
292+ self.assertIn("log(x)+c", results[0]['answer'])
searx/tests/engines/test_wolframalpha_noapi.pynew file+232
@@ -0,0 +1,232 @@
1+# -*- coding: utf-8 -*-
2+from collections import defaultdict
3+import mock
4+from searx.engines import wolframalpha_noapi
5+from searx.testing import SearxTestCase
6+
7+
8+class TestWolframAlphaNoAPIEngine(SearxTestCase):
9+
10+ def test_request(self):
11+ query = 'test_query'
12+ dicto = defaultdict(dict)
13+ dicto['pageno'] = 1
14+ params = wolframalpha_noapi.request(query, dicto)
15+ self.assertIn('url', params)
16+ self.assertIn(query, params['url'])
17+ self.assertIn('wolframalpha.com', params['url'])
18+
19+ def test_response(self):
20+ self.assertRaises(AttributeError, wolframalpha_noapi.response, None)
21+ self.assertRaises(AttributeError, wolframalpha_noapi.response, [])
22+ self.assertRaises(AttributeError, wolframalpha_noapi.response, '')
23+ self.assertRaises(AttributeError, wolframalpha_noapi.response, '[]')
24+
25+ response = mock.Mock(text='<html></html>')
26+ self.assertEqual(wolframalpha_noapi.response(response), [])
27+
28+ html = """
29+ <!DOCTYPE html>
30+ <title> sqrt(-1) - Wolfram|Alpha</title>
31+ <meta charset="utf-8" />
32+ <body>
33+ <script type="text/javascript">
34+ try {
35+ document.domain = "wolframalpha.com";
36+ context = parent ? parent : document;
37+ } catch(e){}
38+ try {
39+ if (typeof(context.$) == "undefined") {
40+ context = window;
41+ } else {
42+ $=context.$;
43+ }
44+ }
45+ catch(e){ context = window;}
46+
47+ try {
48+
49+ if (typeof context.jsonArray.popups.pod_0100 == "undefined" ) {
50+ context.jsonArray.popups.pod_0100 = [];
51+ }
52+
53+ context.jsonArray.popups.pod_0100.push( {"stringified": "sqrt(-1)","mInput": "","mOutput": "", "popLinks": {} });
54+
55+ } catch(e) { }
56+
57+ try {
58+
59+ $("#results #pod_0100:not(iframe #pod_0100)")
60+ .add("#showsteps #pod_0100:not(iframe #pod_0100)")
61+ .add(".results-pod #pod_0100:not(iframe #pod_0100)")
62+ .data("tempFileID", 'MSP44501e0dda34g97a0c8900003i71207d6491ab22')
63+ .data("podIdentifier", '\x22Input\x22')
64+ .data("podShortIdentifier", '\x22Input\x22')
65+ .data("buttonStates", '\x22\x22')
66+ .data("scanner", '\x22\x22');
67+ $("#results #pod_0100-popup:not(iframe #pod_0100-popup)")
68+ .add("#showsteps #pod_0100-popup:not(iframe #pod_0100-popup)")
69+ .add(".results-pod #pod_0100-popup:not(iframe #pod_0100-popup)")
70+ .data("tempFileID", 'MSP44501e0dda34g97a0c8900003i71207d6491ab22')
71+ .data("podIdentifier", '\x22Input\x22')
72+ .data("podShortIdentifier", '\x22Input\x22')
73+ .data("buttonStates", '\x22\x22')
74+ .data("scanner", '\x22\x22');
75+
76+ $("#results #subpod_0100_1")
77+ .add("#showsteps #subpod_0100_1:not(iframe #subpod_0100_1)")
78+ .add(".results-pod #subpod_0100_1")
79+ .data("tempFileID", "MSP44511e0dda34g97a0c89000059490h319161eea3")
80+ .data("cellDataTempFile", "MSP44521e0dda34g97a0c89000011378c50d38ede6h")
81+ .data("tempFileServer", "")
82+ .data("dataSources", "")
83+ .data("sources", "")
84+ .data("sharetype", "1")
85+ .data("shareable", "false");
86+
87+ } catch(e){}
88+
89+ //false
90+
91+ try {
92+
93+ if (typeof context.jsonArray.popups.pod_0200 == "undefined" ) {
94+ context.jsonArray.popups.pod_0200 = [];
95+ }
96+
97+ context.jsonArray.popups.pod_0200.push( {"stringified": "i","mInput": "","mOutput": "", "popLinks": {} });
98+
99+ } catch(e) { }
100+
101+ try {
102+
103+ $("#results #pod_0200:not(iframe #pod_0200)")
104+ .add("#showsteps #pod_0200:not(iframe #pod_0200)")
105+ .add(".results-pod #pod_0200:not(iframe #pod_0200)")
106+ .data("tempFileID", 'MSP44541e0dda34g97a0c8900004f449i50fa482fd8')
107+ .data("podIdentifier", '\x22Result\x22')
108+ .data("podShortIdentifier", '\x22Result\x22')
109+ .data("buttonStates", '\x22Result\x22\x20\x2D\x3E\x20\x7BAll,\x20None,\x20None,\x20None,\x20None\x7D')
110+ .data("scanner", '\x22\x22');
111+ $("#results #pod_0200-popup:not(iframe #pod_0200-popup)")
112+ .add("#showsteps #pod_0200-popup:not(iframe #pod_0200-popup)")
113+ .add(".results-pod #pod_0200-popup:not(iframe #pod_0200-popup)")
114+ .data("tempFileID", 'MSP44541e0dda34g97a0c8900004f449i50fa482fd8')
115+ .data("podIdentifier", '\x22Result\x22')
116+ .data("podShortIdentifier", '\x22Result\x22')
117+ .data("buttonStates", '\x22Result\x22\x20\x2D\x3E\x20\x7BAll,\x20None,\x20None\x7D')
118+ .data("scanner", '\x22\x22');
119+
120+ $("#results #subpod_0200_1")
121+ .add("#showsteps #subpod_0200_1:not(iframe #subpod_0200_1)")
122+ .add(".results-pod #subpod_0200_1")
123+ .data("tempFileID", "MSP44551e0dda34g97a0c8900003gdgd37faa7272e0")
124+ .data("cellDataTempFile", "MSP44561e0dda34g97a0c89000018ea1iae00104g13")
125+ .data("tempFileServer", "")
126+ .data("dataSources", "")
127+ .data("sources", "")
128+ .data("sharetype", "1")
129+ .data("shareable", "false");
130+ } catch(e){}
131+ </script>
132+ </body>
133+ </html>
134+ """
135+ response = mock.Mock(text=html)
136+ results = wolframalpha_noapi.response(response)
137+ self.assertEqual(type(results), list)
138+ self.assertEqual(len(results), 1)
139+ self.assertIn("i", results[0]['answer'])
140+
141+ html = """
142+ <!DOCTYPE html>
143+ <title> integral 1/x - Wolfram|Alpha</title>
144+ <meta charset="utf-8" />
145+ <body>
146+ <script type="text/javascript">
147+ //true
148+ try {
149+ document.domain = "wolframalpha.com";
150+ context = parent ? parent : document;
151+ } catch(e){}
152+ try {
153+ if (typeof(context.$) == "undefined") {
154+ context = window;
155+ } else {
156+ $=context.$;
157+ }
158+ }
159+ catch(e){ context = window;}
160+
161+ try {
162+
163+ if (typeof context.jsonArray.popups.pod_0100 == "undefined" ) {
164+ context.jsonArray.popups.pod_0100 = [];
165+ }
166+
167+ context.jsonArray.popups.pod_0100.push( {"stringified": "integral 1\/x dx = log(x)+constant"});
168+
169+ } catch(e) { }
170+
171+ try {
172+
173+ $("#results #pod_0100:not(iframe #pod_0100)")
174+ .add("#showsteps #pod_0100:not(iframe #pod_0100)")
175+ .add(".results-pod #pod_0100:not(iframe #pod_0100)")
176+ .data("tempFileID", 'MSP2051if2202e8bg0757100000d119b05egf583d3')
177+ .data("podIdentifier", '\x22IndefiniteIntegral\x22')
178+ .data("podShortIdentifier", '\x22IndefiniteIntegral\x22')
179+ .data("buttonStates", '\x22Indefinite\x20integral\x22\x20\x2D\x3E\x20\x7B\x7D')
180+ .data("scanner", '\x22\x22');
181+ $("#results #pod_0100-popup:not(iframe #pod_0100-popup)")
182+ .add("#showsteps #pod_0100-popup:not(iframe #pod_0100-popup)")
183+ .add(".results-pod #pod_0100-popup:not(iframe #pod_0100-popup)")
184+ .data("tempFileID", 'MSP2051if2202e8bg0757100000d119b05egf583d3')
185+ .data("podIdentifier", '\x22IndefiniteIntegral\x22')
186+ .data("podShortIdentifier", '\x22IndefiniteIntegral\x22')
187+ .data("buttonStates", '\x22Indefinite\x20integral\x22\x20\x2D\x3E\x20\x7B\x7D')
188+ .data("scanner", '\x22\x22');
189+
190+ $("#results #subpod_0100_1")
191+ .add("#showsteps #subpod_0100_1:not(iframe #subpod_0100_1)")
192+ .add(".results-pod #subpod_0100_1")
193+ .data("tempFileID", "MSP2071if2202e8bg0757100004dg60f2a4ca8cf73")
194+ .data("cellDataTempFile", "MSP2081if2202e8bg0757100001h18329f72fe90fg")
195+ .data("tempFileServer", "")
196+ .data("dataSources", "")
197+ .data("sources", "")
198+ .data("sharetype", "1")
199+ .data("shareable", "false");
200+
201+ } catch(e){}
202+
203+ //false
204+ try {
205+
206+ $("#results #pod_0200:not(iframe #pod_0200)")
207+ .add("#showsteps #pod_0200:not(iframe #pod_0200)")
208+ .add(".results-pod #pod_0200:not(iframe #pod_0200)")
209+ .data("tempFileID", '')
210+ .data("podIdentifier", '\x22Plot\x22')
211+ .data("podShortIdentifier", '')
212+ .data("buttonStates", '')
213+ .data("scanner", '\x22\x22');
214+ $("#results #pod_0200-popup:not(iframe #pod_0200-popup)")
215+ .add("#showsteps #pod_0200-popup:not(iframe #pod_0200-popup)")
216+ .add(".results-pod #pod_0200-popup:not(iframe #pod_0200-popup)")
217+ .data("tempFileID", '')
218+ .data("podIdentifier", '\x22Plot\x22')
219+ .data("podShortIdentifier", '')
220+ .data("buttonStates", '')
221+ .data("scanner", '\x22\x22');
222+
223+ } catch(e){}
224+ </script>
225+ </body>
226+ </html>
227+ """
228+ response = mock.Mock(text=html)
229+ results = wolframalpha_noapi.response(response)
230+ self.assertEqual(type(results), list)
231+ self.assertEqual(len(results), 1)
232+ self.assertIn("log(x)+c", results[0]['answer'])
searx/tests/test_engines.py+2
@@ -36,6 +36,8 @@ from searx.tests.engines.test_subtitleseeker import * # noqa
3636from searx.tests.engines.test_swisscows import * # noqa
3737from searx.tests.engines.test_twitter import * # noqa
3838from searx.tests.engines.test_vimeo import * # noqa
39+from searx.tests.engines.test_wolframalpha_api import * # noqa
40+from searx.tests.engines.test_wolframalpha_noapi import * # noqa
3941from searx.tests.engines.test_www1x import * # noqa
4042from searx.tests.engines.test_www500px import * # noqa
4143from searx.tests.engines.test_yacy import * # noqa