在单元测试中为Airflow 1.9运行测试Dag

时间:2018-06-26 15:56:34

标签: airflow

我已经实现了用于运行单个dag的测试用例,但是它在1.9中似乎不起作用,可能是由于气流1.8中引入了更严格的存储池 。 我正在尝试在测试用例下运行:

from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator
from airflow.operators.python_operator import PythonOperator

class DAGTest(unittest.TestCase):
    def make_tasks(self):
        dag = DAG('test_dag', description='a test',
                  schedule_interval='@once',
                  start_date=datetime(2018, 6, 26),
                  catchup=False)


        du1 = DummyOperator(task_id='dummy1', dag=dag)
        du2 = DummyOperator(task_id='dummy2', dag=dag)
        du3 = DummyOperator(task_id='dummy3', dag=dag)
        du1 >> du2 >> du3
        dag.run()

    def test_execute(self):
        self.make_tasks() 

例外:

Dependencies not met for <TaskInstance: test_dag.dummy3 2018-06-26 00:00:00  [upstream_failed]>, dependency 'Trigger Rule' FAILED: Task's trigger rule 'all_success' requires all
    upstream tasks to have succeeded, but found 1 non-success(es).
    upstream_tasks_state={'skipped': 0L, 'successes': 0L, 'failed': 0L,'upstream_failed': 1L, 'done': 1L, 'total': 1}, upstream_task_ids=['dummy2']

我做错了什么? 我已经尝试过LocalExecutor和SequentialExecutor

环境:

Python 2.7
Airflow 1.9

我相信它正在尝试同时执行所有任务而又不遵守依赖关系。 注意:在Airflow 1.7中使用类似的代码

2 个答案:

答案 0 :(得分:1)

我不熟悉Airflow 1.7,但我想它没有与Airflow1.8及更高版本相同的“ DagBag”概念。

您无法运行这样创建的DAG,因为dag.run()启动了一个新的python进程,它将必须从它在磁盘上解析的dag文件夹中找到DAG-但它不能。这已作为消息包含在输出中(但您没有包括完整的错误消息/输出)

您要通过在测试文件中创建dag来测试什么?它是自定义运算符吗?那么您最好直接进行测试。例如,这是我如何独立测试自定义运算符的方法:

class MyPluginTest(unittest.TestCase)
    def setUp(self):
        dag = DAG(TEST_DAG_ID, schedule_interval='* * * * Thu', default_args={'start_date': DEFAULT_DATE})
        self.dag = dag
        self.op = myplugin.FindTriggerFileForExecutionPeriod(
            dag=dag,
            task_id='test',
            prefix='s3://bucket/some/prefix',
        )
        self.ti = TaskInstance(task=self.op, execution_date=DEFAULT_DATE)

        # Other S3 setup here, specific to my test


    def test_execute_no_trigger(self):
        with self.assertRaises(RuntimeError):
            self.ti.run(ignore_ti_state=True)

        # It shouldn't have anything in XCom
        self.assertEqual(
            self.ti.xcom_pull(task_ids=self.op.task_id),
            None
        )

答案 1 :(得分:0)

这是可以在pytest测试用例中使用的功能,该功能将按顺序运行DAG的任务。

from datetime import timedelta
import pytest
from unittest import TestCase


@pytest.fixture
def test_dag(dag):
    dag._schedule_interval = timedelta(days=1)  # override cuz @once gets skipped
    done = set([])

    def run(key):
        task = dag.task_dict[key]
        for k in task._upstream_task_ids:
            run(k)
        if key not in done:
            print(f'running task {key}...')
            date = dag.default_args['start_date']
            task.run(date, date, ignore_ti_state=True)
            done.add(key)
    for k, _ in dag.task_dict.items():
        run(k)

然后可以在测试中使用test_dag(dag)代替dag.run()

您需要确保登录自定义运算符时使用的是self.log.info()而不是logging.info()print(),否则它们不会显示。

您可能还需要使用python -m pytest -s test_my_dag.py运行测试,因为如果没有-s标志,将不会捕获到气流的标准输出。

我仍在设法弄清DAG之间的依赖性。