年前志愿离职,苦逼面试记录

公司融资失败了,10月志愿离职拿了赔偿,记录一下苦逼的面试,和躺平的生活

没有骑驴找马,离职半个月后开始找工作

总结1:如果你没有面试机会,一定是投的简历不够多,以量取胜

面试1: 腾讯音乐,一位不愿露面的老哥面试,提前说会有算法题目,从没刷过算法题目,准备了10道算法题,结果一道没遇到,直接上应用,GG。

问题1:一个4g大的qq账号文件,如何排序到另一个文件。

答:这道题杀了我个错手不急,没有答好,想到多线程加锁处理源和目标文件,没有想到怎么排序,说到目标以后再排序,这里感觉到目标可以使用插入排序(大佬可以说说解法),这道题没答好,直接GG了。

问题2:如何做持续集成

答:巴拉巴拉~
其他忘记了,反正肯定没戏了。

面试2:

隔了大概一周,都快躺平了,来了第二个面试,一个做图数据库的公司,因为开始以量取胜,在boss上直接投到手软,终于有了一个面试邀请。面试的是位小姐姐,好评。

问题1:自我介绍

答:巴拉巴拉~

问题2:如何做自动化

答:回答了我做接口自动化的两大模块,如何做分层,如何做数据校验;UI自动化做了那些

问题3:docker常用命令

答:docker pull、docker run、docker stop、docker start、docker exec -it … bash,并配上使用场景

问题4:负责产品的功能模块

答:巴拉巴拉~

问题5:一个sql 查询语句,应该是一个左联,写成子查询了,但好久没写这种sql,写错了

问题6:基础算法题,两数之和,这个刷到过,正常答完

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        res = []
        # 创建哈希表,两元组分别表示值、下标
        hash = dict()
        # 在哈希表中查找target-numbers[i]
        for i in range(len(numbers)):
            tmp = target - numbers[i]
            # 若是没有找到,将此信息计入哈希表
            if tmp not in hash:
                hash[numbers[i]] = i
            else:
                #哈希表中记录的是之前的数字,所以该索引比当前小
                res.append(hash[tmp] + 1)
                res.append(i + 1)
                break
         return res

补充问题7:用过那些数据库

大概列举了常用的数据库
Oracle、Mysql、Postgres、Sqlserver、TiDB、Oceanbase、KunDB、Redis、MongoDB、Dameng、Kingbase、Kafka、rabbitMQ、rocketMQ、ActiveMQ、Hbase、Greenplum、Hbase、等等,面试官对消息队列的同步比较感兴趣,和她大概聊了一下产品模型推演相关的概念

反问:图数据库如何实现的高可用?是否有存储过程?与RDBMS的区别?

就是和面试官讨论一下,其实对它们的图数据库还是有点兴趣的,不给面试岗位不是这一部门的,面试官没有说的很详细

HR反馈还可以,等待二面

哈哈害,面试2,二面来了,又是一位小姐姐。

问题一: 自我介绍

问题二:公司产品介绍,自动化难点

答:先介绍背景,巴拉巴拉~,再介绍产品,巴拉巴拉~,再介绍自动化难点,巴拉巴拉~

问题三:docker 网络模式

答:三种,桥接,localhost,none;这里应该还有一种container模式,和容器之间建立网络,这里答错了。

问题四:docker -p 和 -v的作用

答:指定端口映射,指定容器数据宿主机存储位置

问题五:图数据库是否了解

答:用图的数据结构来描述数据之间的关系,在某些场景下性能表现优异

问题六:图的搜索算法

答:广度优先算法、和深度优先算法,用口语化的方式描述了一下,应该还好

问题七:你在上一家公司有有什么提升?

答:丰富了自己的业务场景,实践了自己的自动化测试设计和代码,对持续集成有了新的认识。

会议室有人用,时间不太够,只面试了10分钟左右,但感觉应该过了,依然自我感觉良好的代表,哈哈害

面试3:

一家自动驾驶公司,面试得岗位应该是和算法相关的测试岗位,我的电脑没有摄像头,所有是在手机上面通过牛客进入面试的,面试官声音有点小,挺难受的,而且面试流程有点长,问题较多,总体面试效果还不错。

问题1:说一下公司的测试流程

答:这里没有完全以我们公司的测试流程来说,因为之前公司的流程并不规范,按照之前在招行的流程说的:
1.产品经理首先提出需求卡片,然后开发、测试、项目经理、产品的评审需求是否合理,是否加入迭代;
2.开发编写设计文档并拉相关人员进行评审(评审通过进入下一步);
3.测试进行需求分析,编写相关的测试需求分析文档,制定测试计划、测试策略、测试案例(冒烟案例),拉相关人员进行评审(评审通过进入下一步);
4.有个小的测试准备步骤,准备测试数据、测试环境;
5.开发提测,执行冒烟案例,通过后进入第一轮测试,提交bug(bug流程-状态流转-开发-测试-产品battle)
6.开发修改完bug以后进入第二轮测试,测试通过进入下一流程,测试不通过增加轮次或作bug遗留处理,这里依赖产品准入准出标准(需要提前制定)
7.测试总结,包含测试报告,测试回顾、复盘等内容,不要觉得麻烦,有时候会发现意想不到的需求不对齐的bug
我大概说了这几点,还有细节需要自己补充,晚上6:30开始的面试,感觉自己说起来滔滔不绝,文思泉涌,还想扯一下不同的招行流程的区别,想想算了,感觉晚上面试会更有状态,老铁们可以根据自己情况把重要面试,安排到晚上。

问题2:python相关的,字典和元组区别,生成器、迭代器、装饰器原理说明

答:字典是一个键值对,元组是一个不可变的列表,生成器和迭代器,这个好久没复习了,有点忘记了,我说的是一个可以不停拿取元素的容器,哈哈哈,可以通过鸭子方法来实现一个对象的迭代特性,后面查了一下,也不是太错:

在 Python 中创建迭代器的一种方法是定义一个实现方法__init____next__ . 我们通过实现一个类循环来展示这一点,该循环可用于永远循环遍历一个可迭代对象。换句话说,这个类的一个实例返回一个可迭代的元素,直到它用完为止。然后它无限期地重复该序列。

生成器没有问,只是我这边顺便提出来:

生成器就像函数一样被调用。它的返回值是一个迭代器,即生成器对象。生成器的代码不会在这个阶段执行。
迭代器可以通过调用 next 方法来使用。第一次执行像函数一样开始,即迭代器主体内的第一行代码。代码会一直执行,直到到达 yield 语句。
yield返回表达式的值,它跟在关键字 yield 之后。这就像一个函数,但是 Python 会跟踪这个 yield 的位置,并且会存储局部变量的状态以备下次调用。在下一次调用时,继续执行 yield 语句之后的语句,并且变量的值与它们在前一次调用中的值相同。
如果生成器主体已完全运行或程序流遇到没有值的返回语句,则迭代器已完成。

和python的协程有关,知识真的是不用就忘了。

装饰器,这里我讲了项目中用到的自己写的日志装饰器,函数装饰器,没有讲类装饰,面试官还算满意,类装饰的,我也不太清楚了

查询个小例子打打样:

import time 
class Timer:
    def __init__(self,func) -> None:
        self.func = func
  
    def __call__(self, *args, **kwargs):
        start = time.time()
        ret = self.func(*args, **kwargs)
        print(f'Time:{time.time()-start}')
        return ret
        
@Timer
def add(a,b):
    time.sleep(1)
    return a+b

print(add(2,3))

函数装饰器原理:

这里就自由发挥,说一下自己的理解,函数装饰器的实质还是一个函数,通过传输产生为函数的方式来实现一些对函数额外功能的添加,就是在函数中的定义中再加一个函数,最外层传的参数,就是你要装饰的函数,例子:

def func_logger(robot):
    """
    语句执行装饰圈日志
    :param robot:
    :return:
    """

    @wraps(robot)
    def conLog(*args, **kwargs):
        if args:
            logger.info(f'args >>> {args}')
        if kwargs:
            logger.info(f'args >>> {kwargs}')
        result = robot(*args, **kwargs)
        logger.info(f'return is >>> {result}')
        return result

    return conLog

带参数的装饰器:

就是函数的函数里面再定义一个函数,第一层函数参数为装饰器参数,第二层函数参数为被装饰对象,第三层为装饰器的执行逻辑,例子:

def more_time_check(assert_thing, outer_time, interval=5):
    def middle(func):
        def check(*args, **kwargs):
            for _ in range(outer_time):
                result = func(*args, **kwargs)
                logger.info(result)
                if result == assert_thing:
                    logger.info(result)
                else:
                    logger.fatal(result)
                    raise f'assert_thing not equals {assert_thing}'
                time.sleep(interval)

        return check

    return middle

python相关内容大概就这些,面试官还算满意,也可能是我自我感觉良好

问题3:docker相关的命令,这个差不多就那几个,都是比较常用的,面试2已经遇到了

docker pull name/version 拉取镜像
docker rm image name/version 删除镜像
docker start name 启动
docker stop name 停止
docker logs -f name 查看容器日志
docker exec -it name bash 进入容器
docker rm -f name 删除容器

问题4:内存泄漏和内存溢出的区别

哈哈哈,好巧不巧,前两天在ceshiren上面刚好看到了这个题目,内存泄漏是指开发在代码中没有释放资源,导致内存被无端占用,内存溢出是指服务器内存被占用完,没有空余的内存资源;很快啊,一个右鞭腿,一个左正蹬,面试官没有闪,我就回答完了。

问题5:常用的linux命令

ps -ef 进程查询
top 监控
tail -n200 filename|grep ... 平时用什么查日志
jps 查看java进程
...
还有些啥忘记了,但是也还答得不错

问题6:你是如何做的自动化,可扩展性怎么样

这块就说了一下自己的代码,这里就大概说了一下自己的代码实现,目前还没有开源,主要里面有些公司之前的认证算法,和服务器信息。
https://gitee.com/zsjlovewm/tap-client-v3
主要说了一下分层设计的好处,还有针对与公司产品的框架,扩展性没有那么好,因为要贴合公司的业务,说了其他的单独的xx的模块扩展性比较好,有单独的命令行查询工具可以查询相关的数据库信息。

有时候面试着突然就忘了面试官问题,然后自己就一直说下了,哈哈哈哈

问题7:你的框架用了什么设计模式?

哈哈哈,这个之前还真没想过,也是上周去学习了菜鸟教程才知道,之前只看了前面三个设计模式,工厂模式、抽象工厂模块、单例模式,无意中发现,自己代码在接口层那里使用了工厂模式,然后就说了工厂模式,然后再说了一下如何实现的代码 工厂模式 | 菜鸟教程

问题8:git命令

git add 添加git文件管理
git commit 本地代码提交
git pull 拉去代码
git push 远程代码提交
git branch 查看分支
git checkout 切换分支

反问:公司是什么业务?,自动化驾驶测试中逻辑功能、仿真功能、健壮性功能测试?这个职位的主要工作?benchmark的内容

一般面试公司我都会有备而来,去查询了一下相关的业务测试技术文章,拽两句还是很有必要的,哈哈哈,了解职位是测试算法的,然后用的是c++,还是很有挑战性的,面试官还问了一下我对c++代码熟不熟,我说看函数方法应该没什么问题,倾向于白盒测试。

其他:因为是用的手机,有算法题,但是面试官说算了,后期准备买一个摄像头,这样就能在电脑上编程了。

早上HR反馈,初面过了,等待二面

3 个赞

感谢分享~