blob: 70ecb612ccc61297cbf05f909215a586bbbaff06 [file] [log] [blame]
# -*- coding: UTF-8 -*-
# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""This is sample code of a board specific test.
Board specific test should be put in board overlay, e.g.
~/trunk/src/private-overlays/overlay-${BOARD}-private/chromeos-base/chromeos-factory-board/files/py/pytests/
To avoid file name conflict, please name the python script as "${BOARD}_xxx.py".
For example, if you are implementing your own touchscreen test for board ABC, a
reasonable file name would be: abc_touchscreen.py.
"""
import logging
import unittest
import factory_common # pylint: disable=unused-import
from cros.factory.device import device_utils
from cros.factory.test import factory
from cros.factory.test import testlog
from cros.factory.utils import arg_utils
class SampleCustomizedTest(unittest.TestCase):
"""Example of how to write a pytest.
The pytest must inherit `unittest.TestCase`, and implement `runTest` function.
The `runTest` function is similar to the main function of the test. When the
test starts, this function will be called. You can also implement `setUp` and
`tearDown` functions to make sure something is done before / after the test,
no matter what.
"""
ARGS = [
arg_utils.Arg(
'foo', int, help='foo can only be int, not optional'),
arg_utils.Arg(
'bar', str, help='bar is optional, default to None',
optional=True),
arg_utils.Arg(
'baz', str, help='baz is optional, default to "BAZ"',
default="BAZ"),
]
"""Arguments of this pytest.
Arguments of a pytest is defined by class variable "ARGS", which must be a
list of `cros.factory.utils.arg_utils.Arg` object. You can specify the value
of each argument in the test list:
FactoryTest(
...,
dargs={
'foo': 123,
'bar': 'value of bar',
# not setting value of 'baz', it will use default value.
})
"""
def setUp(self):
"""Setup function."""
self.dut = device_utils.CreateDUTInterface()
# from now on, you can use `self.dut` to control stuff on DUT
# for example, create a temporary folder on DUT
self.temp_dir = self.dut.temp.mktemp(is_dir=True)
def tearDown(self):
"""Tear down function (for clean up)."""
# remove the folder we created, and everything inside that folder.
self.dut.CheckCall(['rm', '-rf', self.temp_dir])
def runTest(self):
"""Main function of the test. Implement test logic in this function."""
# for example, measure some value on DUT.
photo_path = self.TakePhoto()
# when you use logging, the message will be logged by testlog automatically.
logging.info('Image captured, attaching to testlog...')
# attach the file to the testlog
testlog.AttachFile(
path=photo_path, mime_type='image/jpeg', name='front_camera.jpeg',
description='image captured by the front camera for quality test.')
quality = self.ComputePhotoQuality(photo_path)
# check and log the value, note that testlog will NOT fail the test for you,
# you have to raise an exception by yourself.
if not testlog.CheckParam(
name='photo_quality',
value=quality,
min=0.9, max=1.0,
description='Quality of the photo'):
raise factory.FactoryTestFailure('The camera is not qualified')
# you can also measure and log a series of values
series_logger = testlog.CreateSeries(
name='audio_quality',
description='quality of audio device on different frequency',
key_unit='Hz', value_unit='quality')
failed = False
for freq in xrange(1000, 4000, 50):
quality = self.MeasureAudioQuality(freq)
if not series_logger.CheckValue(
key=str(freq), value=quality, min=0.8, max=None):
failed = True
if failed:
raise factory.FactoryTestFailure('The audio device is not qualified')
def TakePhoto(self):
raise NotImplementedError
def ComputePhotoQuality(self, photo_path):
raise NotImplementedError
def MeasureAudioQuality(self, freq):
raise NotImplementedError